シナリオの説明から始めましょう。SQL Server 2008 を使用する MVC 3 アプリケーションがあります。ページの 1 つで、データベースから返され、ログインしたユーザーごとに一意である製品のリストを表示します。製品のリストを返すために使用される SQL クエリ (実際には VIEW) は非常に高価です。
- これは、現段階では変更できない非常に複雑なビジネス要件に基づいています。
- データベース スキーマは、他のアプリケーションで使用されているため、変更または再設計することはできません。
- 50,000 個の製品と 5,000 人のユーザーがいます (各ユーザーは 1 個から 50,000 個の製品にアクセスできます)。
ログインしたユーザーの製品ページを表示するには、次を使用します。
SELECT TOP X * FROM [VIEW] WHERE UserID = @UserId -- where 'X' is the size of the page
上記のクエリは、最大 50 行 (最大ページ サイズ) を返します。WHERE 句は、行数を最大 50k (ユーザーがアクセスできる製品) に制限します。ページの読み込みに約 5 ~ 7 秒かかります。これは、上記の SQL クエリを SQL で実行するのにかかる時間とまったく同じです。 問題:
ユーザーは製品ページに移動し、ページングを使用して結果を再ソートし、詳細ページに移動してからリストに戻る可能性が非常に高くなります。そして、結果を表示するのに 5 ~ 7 秒かかるたびに。
これは受け入れがたいことですが、同時に、ビジネス チームは、商品ページが最初に読み込まれるときに 5 ~ 7 秒かかることを認めています。したがって、 CACHINGについて考えました。
選択できるオプションが 2 つあります。少なくとも私にとって最も「明白な」オプションは、.Net キャッシュ (メモリ内/プロセス内) を使用することです。(現時点では、プロバイダー/ホスティング パートナーの技術的な制約により、分散キャッシュは許可されていないことに注意してください)。
しかし、私はこれにあまり満足していません。コードが新しいアイテムを挿入している間に.Netがキャッシュアイテムを絶えず削除してスペースを解放するなど、サーバーに他の問題を引き起こす可能性がある(50人または100人のユーザーが同時にログインしている場合)メモリ内に多くの製品が残る可能性があります。
2番目のオプション:
ここでの主な問題は、ユーザー x 製品 x アクセス ビューを生成するのに非常にコストがかかることです。そのため、フラット テーブル (つまり、データベース内のすべての製品 x ユーザーのキャッシュ) を作成できると考えました。このテーブルは、まさにビューの結果です。ただし、新しい製品が追加されたり、ユーザー権限が変更されたりすると、結果はいつでも変更される可能性があります。そのため、テーブルを常に更新する必要があり (数秒かかる場合があります)、これが少し複雑になり始めました。
同様に、ある種のキャッシュ プロバイダーを実装し、ユーザーからの要求に応じて、元の SQL クエリを実行し、ビューから製品を選択し (5 ~ 7 秒、1 回のみ許容)、その結果をフラットに保存します。 SQL では ProductUserAccessCache と呼ばれるテーブル。次のリクエストでは、このキャッシュされたテーブルから値を取得します (その特定のユーザーに対して結果がキャッシュされたことを簡単に識別できるため)。SQL での計算を行わない高速クエリを使用します。製品が追加されるか権限が変更されるたびに、キャッシュされたテーブルが切り捨てられ、新しいリクエストがあったときに、リクエストされたユーザーのテーブルが再作成されます。私にはそれほど複雑ではないように思えますが、基本的にここで行っていることは、新しいキャッシュ「プロバイダー」を作成することです。
- この種の問題を経験した人はいますか?
- .Net Caching (in proc) を使用したほうがよいでしょうか?
- 助言がありますか?