2009-08-13 12 views
2

のは、私がウェブサイト上の記事を持っている、と私は記事へのビューの数を追跡したいとしましょう。アーティクルテーブルには、PK ID-int、Name-nvarchar(50)、およびViewCount-intがあります。ページが表示されるたびに、私はViewCountフィールドをインクリメントします。私はフィールドを更新するときに衝突が心配です。私の恐怖は、私は、このモデルではカウントされないページビューで終わるつもりだということですに増分DBフィールド

CREATE PROCEDURE IncrementView 
(
    @ArticleID int 
) 
as 

BEGIN TRANSACTION 

UPDATE Article set ViewCount = ViewCount + 1 where ID = @ArticleID 

IF @@ERROR <> 0 
BEGIN 
    -- Rollback the transaction 
    ROLLBACK 

    -- Raise an error and return 
    RAISERROR ('Error Incrementing', 16, 1) 
    RETURN 
END 

COMMIT 

:私は次のようにトランザクションとSPROCでそれを実行することができます。他の可能な解決策は、実際に記事にビューを記録し、記事へのビュー数に関するデータを取得するために関数とビューの組み合わせを使用するモデルのログタイプです。

答えて

2

おそらく、より良いモデルは、アプリ内で1時間ごとにビューの数をどこかにキャッシュしてから、バッチスタイルのプロセスで更新することです。

- 編集:

がより精巧にするためには、あなたのための単純なモデルであってもよい:

  1. 各ページの負荷は、特定のページのために、静的なHashMapをインクリメントします。また、各負荷で、「最終更新」から十分な時間が経過したかどうかを確認し、更新されている場合は更新を実行します。

  2. asp.netキャッシュ(http://msdn.microsoft.com/en-us/library/aa478965.aspx)に基本値を入れ、タイムアウトすると[リンクに記載されているようにキャッシュ削除ハンドラを実装する]更新を行います。 1時間のタイムアウトを設定します。

どちらのモデルでも、静的なページマップがカウントされます。このビューを更新し、現在の '生きている'カウントを取得するために、これとキャッシュされたdbの量も使用します。

+0

ナー、リアルタイムになる必要があります。あなたがこのサイトを見ていても、それはビュー数でリアルタイムで動作しています。 – Darthg8r

+0

これは明らかにリアルタイムで表示されることができますが、_database_リアルタイムには表示されません。変数は静的にすることができます。 –

+0

+1うーん、悪くない。私はasp.netを使っていたと思っていました...幸いにも、私は幸いです。あなたのモデルでは、lock()を使ってその静的ハッシュ/キャッシュ項目を安全にすることができます。 – Darthg8r

2

データベースは、1桁の増分をアトミックに処理できる必要があります。競合が発生する可能性がある場合は、キューのクエリを順番に処理する必要があります。あなたのより大きな問題は、ボリュームが十分な場合、同じ行へのすべての書き込みを処理することです。それぞれの書き込みは、その後ろの読み書きをブロックします。心配しているならば、SQLアップデートを連続して呼び出し、数百の同時スレッド(ハードウェアが飽和するまでスレッドを増やす)で実行する簡単なプログラムを作成します。試行が最終結果であることを確認してください。

絹のようなバッチ更新をキャッシュしたり実行したりする仕組みを見つけることは、勝者のように思えます。

ヤコブ

+0

私はdbをハンマーでテストし、出力をチェックするテストプロジェクトのアイデアが気に入っています。 – Darthg8r

0

あなたは、SQL Serverの単一の更新ステートメント内の並行性を心配する必要はありません。
しかし、あなたは、2人のユーザが第二の同じ第十にテーブルを打つ心配している場合は、その日の秒864000 10があることに留意してください。記事を提供しているページで問題になるようなものではないと思います。

0

は心配がありません!

このアップデートは単一の(アトミック)トランザクションです。あなたは「衝突」を得ることはできません。 IncrementViewへの5,000,000回の呼び出しがすべて同じタイミングでデータベースにヒットしたとしても、ファンクションのような連続したキューで処理されます。つまり、データベースエンジンを使用しているものと同じです。各呼び出しは行(少なくとも)に対して排他的な更新ロックを取得します。したがって、後続の問合せでは、現在のコミットがコミットされるまで行を更新することはできません。

BEGIN TRAN ... COMMITを使用する必要はありません。更新に失敗した場合は、とにかくロールバックするものはありません。

私は、任意のアプリのキャッシュの必要性が表示されていない - このアップデートは長い時間がかかるだろうADNので、あなたのアプリケーションのパフォーマンスに影響を与えないべき理由理由はありません。 [比較的うまく設計されていると仮定して]