2011-01-20 7 views
2

各投票がまたはのいずれかのint -1とともにUserIDと投票のDateTimeと投票表に取り込まれることにより、私は投票システムを構築しています。投票システム:SQLトリガー以上のコードを使用する必要がありますか?

また、ユーザが実際に投票したアイテムを含むテーブルには、合計がTotalVotesになります。この方法では、投票テーブルSUMへのクエリを常に実行しているわけではありません。

私の質問は、TotalVotesフィールドを更新する際の賛否両論の質問です。コードの管理性に関しては、アプリケーションに追加の更新メソッドを追加することで、トラブルシューティングや潜在的な問題の発見が容易になります。しかし、このアプリケーションがユーザベースで大幅に増加すると、アプリからDBへの追加のSQL呼び出しが発生する可能性があります。トリガを使用すると、「SQLファミリのすべてを」ということが言えるようになります。また、パフォーマンスを少し向上させるだけでなく、コードベースから日常的な活動を守る必要があります。

この特定の質問では時期尚早の最適化を呼び出すことができると私は理解していますが、まだ構築していないので、ゲートからすぐれたアプローチを試してみることもできます。

私は個人的にトリガーに向かっています。あなたの思考/推理を教えてください。

+1

あなたは 'SUM the Vote table'が確かに予算予算の範囲外であると判断しましたか? –

答えて

1

私は何年もの間トリガー方法を行ってきましたが、いつもより幸せでした。だから、彼らが言うように、「入ってきて、水は大丈夫です」。しかし、私は通常、1つではなく、多くのテーブルが関わっているときにそれを行います。

賛否両論はよく知られています。値を具体化することは「今すぐ支払う」という決定であり、あなたはより速い読みを得るために挿入物に少しだけ支払うことになります。これは、500ミリ秒の代わりに5ミリ秒で読み込みを行う場合にのみ、移動する方法です。

PRO:TotalVotesは常に1つの読み取りで即座に利用できます。

PRO:コードパスを心配する必要はありません。挿入を行うコードははるかに簡単です。大規模なアプリケーションでは多くのテーブルに掛け合わされていますが、これは保守性の点で大したことです。

CON:INSERTごとに、さらにUPDATEを支払う必要があります。あなたがこれに気づく前に、多くの人が思うよりも多くのインサート/秒が必要です。

CON:多くのテーブルでは、トリガーを手動でコーディングするのが難しい場合があります。私はコードジェネレータを推奨しますが、私が知っている唯一のものを書いたように、それは私を自己宣伝の領域にしてくれるでしょう。テーブルが1つしかない場合は、手動でコード化してください。

CON:完全性を保証するために、コンソールまたはコードからUPDATEを発行してTotalVotesを変更することはできません。これはもっと複雑であることを意味します。トリガーは、通常は使用されない特別なスーパーユーザーとして実行する必要があります。親テーブルの2番目のトリガーは、更新時に発生し、更新を行うユーザーが特別なスーパーユーザーでない限り、TotalVotesへの変更を防ぎます。

これはあなたに決定するのに十分です。

+0

「コードはできません「TotalVotesを更新する」。ちょうどその余分な仕事;-)の多くのために –

+0

"それはあなたがこれに気付く前に、ほとんどの人が思うより多くの挿入/秒を要します。" - 私は、この特定のプロジェクトは、投票率が2番目のしきい値に達することはないと思っています。これは、比率が数千以上になると思っているためです。 –

+0

ああ、そしてFYI - 私はすべてのデータアクセスにORM(Linq to SQL)を使用しているので、簡単に 'VoteCount'を' ReadOnly'に設定することができます。 –

1

私の最初の勇気は、SUM操作を実行するためのUDFを作成し、そのUDFに基づいて計算された列をTotalVotesにすることです。

+0

+1私はUDFを研究し、これを行う方法を考えなければならないと思います:-s –

2

投票集計と更新の両方を行うストアドプロシージャを作成することをお勧めします。あなたのアプリケーションは、投票の記録方法を知っていればよいのですが、あなたが呼び出すときに起こっていることを正確にロジックが1つの場所(ストアドプロシージャではなく、アドホックな更新クエリと別のトリガ) 。

これは、後で総投票数の更新を削除する場合は、更新部分をコメントアウトすることで変更するだけで済みます。

+0

+1ありがとうございます。私はSPの場所を持っていることを認識し、これは間違いなくそれらの一つかもしれませんが、私の特定のアプリケーションでは、私はSPのすべてのコストを避けています。 –

+0

ああ。その場合、トリガーは確かに実行可能なオプションです。 :)そのフィールドのインデックスは、SUM()を必要とせずにパフォーマンスの問題を否定するのに十分な速さにするかもしれません。 – Tridus

2

早すぎる時期尚早の最適化は、必要に応じてデータを合計するのではなく、テーブルに合計を保存することです。あなたは本当にパフォーマンスのためにデータを非正規化する必要がありますか?

データを非正規化する必要がない場合は、トリガーを作成する必要はありません。

+0

投票表は数十から数十万レコードに拡大し、総投票数はほぼすべてのページに表示されます。はい、私は毎回それを合計する以上に最適化する必要があります。 –

+0

@rockinthesixstring:試してみるまでノックしないでください。テーブルを作成して偽のデータを生成し、提案されたソリューションのパフォーマンスを分析することをお勧めします。 –

3

もう1つの選択肢は、voteVolderとして投票を集計する投票表のビューを作成することです。 次に、ビューのインデックスを作成します。

SQL Serverオプティマイザの魔法(エンタープライズ版のみだと思います)は、sum(voteColumn)のクエリを見ると、同じデータのビューのインデックスからその値を選ぶことになりますクエリで直接ビューを参照していないと考えてください。

エンタープライズエディションをお持ちでない場合は、テーブルではなくビューの投票総数を照会し、インデックスを利用することができます。

インデックスは、基本的に、オプティマイザが認識しているデータの非正規化です。必要に応じて作成または削除し、オプティマイザが把握できるようにします(コードを変更する必要はありません)。手作業で作成された非正規化のパスを開始すると、コードに数年間保存されます。

チェックアウトImproving performance with indexed views

作業インデックス付きビューを取得するために満たされなければならないいくつかの具体的な基準があります。ここにあなたのデータモデルの推測に基づくサンプルです:

create database indexdemo 
go 
create table votes(id int identity primary key, ItemToVoteOn int, vote int not null) 
go 

CREATE VIEW dbo.VoteCount WITH SCHEMABINDING AS 
select ItemToVoteOn, SUM(vote) as TotalVotes, COUNT_BIG(*) as CountOfVotes from dbo.votes group by ItemToVoteOn 
go 
CREATE UNIQUE CLUSTERED INDEX VoteCount_IndexedView ON dbo.VoteCount(itemtovoteon) 
go 
insert into votes values(1,1) 
insert into votes values(1,1) 
insert into votes values(2,1) 
insert into votes values(2,1) 
insert into votes values(2,1) 
go 

select ItemToVoteOn, SUM(vote) as TotalVotes from dbo.votes group by ItemToVoteOn 

そして、このクエリ(ビューを参照しないか、拡張機能によって、それのインデックス)は、この実行計画での結果。インデックスが使用されていることに注意してください。もちろん、最後の言葉を、インデックスを削除(および挿入のパフォーマンスを得る)

alt text

そして、もう一つ。あなたが稼働していない限り、どのような種類の非正規化が実際に全体のスループットに役立つかを知る方法を実際に知っています。索引を使用すると、索引を作成したり、役立つかどうかを測定したり、必要に応じて索引を保持または削除することができます。これは、実行するのが安全な唯一の非正規化です。

+0

ありがとうございます。私の質問ですが、既に選択しているテーブルにVoteCountを入れて、投票が行われたときに単にそれを更新するのは意味がありませんか?私が置いているよりも多くのデータを引き出すと、最終的な数が既に設定されているのではなく、計算を追加するのは意味がありません(少なくとも私にとって)。ちょっと考えて... –

+0

この種のインデックス作成では、キャッシュとインデックスの相対的に小さなサイズのために、サーバーは結果をかなり迅速に処理できるはずです。あなたは必ずしも列を持ち、その上で大量の更新を行うことで多くのパフォーマンスを得られるとは限らないので、速いインデックスから外れます。 – Tridus

+0

@rockinthesixstring ---インデックス付きビューは、TotalVotes列と同じことを行います。投票テーブルに挿入するたびに、ビューの更新が必要です(集計が加法的であるために行うことができます)。その列を合計するコストが現在の合計を維持するコストインデックスを削除してください。それはすべて生産環境に依存します(もちろん、時間の経過とともに変化し、コードには望みません)。 –

関連する問題