1

AppFabric キャッシュに関するドキュメントをたくさん読みましたが、そのほとんどは単純なシナリオをカバーしています。たとえば、都市リスト データやショッピング カード データをキャッシュに追加します。しかし、製品カタログ データをキャッシュに追加する必要があります。

私は4つのテーブルを持っています:

Product (100 万行)、ProductProperty (2,500 万行)、Property (100 行)、PropertyOption (300 行)

  • Product および ProductProperty テーブルのいくつかのフィルターを使用してクエリを実行し、ページ化された検索結果を表示します。
  • 検索結果セットに対して基準セットを作成しています。例 (4 アイテムの新製品、34 アイテムの電話、26 アイテムの書籍など)
  • IsNew、CategoryId、PriceType などの列を使用して Product テーブルをグループ化するため
    のクエリを実行し、PropertyId および PropertyOptionId 列を使用して ProductProperty テーブルをグループ化する別のクエリを実行して、どのプロパティにアイテムがいくつあるかを取得します。

したがって、検索結果を表示するには、検索結果に対して1つのクエリを作成し、基準リストを作成するために2つのクエリを作成します(カウント付き)

検索結果のクエリに 0.7 秒、2 つのグループ化クエリに合計 1.5 秒かかりました。負荷テストを実行すると、1 秒あたり 7 リクエストに達し、%10 が IIS によってドロップされました。これは、db が応答を返すことができなかったためです。

これが、製品とプロパティのレコードをキャッシュしたい理由です。

以下の項目に従う場合 (AppFabric 内);

  • 名前付きキャッシュを作成する
  • 製品カタログ データのリージョンを作成します (100 万行のテーブルと 2,500 万行のプロパティ テーブル)。
  • データのクエリとグループ化のためのタグ付けアイテム。

いくつかのタグを使用してクエリを実行し、結果の 1 ページ目または 2 ページ目を取得できますか? いくつかのタグを使用してクエリを実行し、いくつかのグループ化結果の数を取得できますか? (フィルターオプションをカウントで表示) そして、3 台のサーバーが必要ですか? appfabric サーバーが 1 つだけのソリューションを提供できますか (もちろん、リスクは承知しています)。これらのシナリオについて説明している記事やドキュメントをご存知ですか?

ありがとう。

ノート:

いくつかの追加テスト: 約 30.000 項目をキャッシュに追加しました。そのサイズは 900 MB です。getObjectsInRegion メソッドを実行すると、約 2 分かかりました。「IList> dataList = this.DataCache.GetObjectsInRegion(region).ToList();」問題は IList への変換です。IEnumerable を使用すると、非常に迅速に動作します。しかし、自分のタイプに変換せずにページングまたはグループ化の結果を取得するにはどうすればよいですか?

別のテスト:

30.000 個の商品アイテムでグループ化カウントを取得しようとしましたが、グループ化の結果を取得するのに 4 秒かかりました。たとえば、GetObjectByTag("IsNew").Count() などの約 50 のクエリがあります。

4

1 に答える 1

2

残念ながら、V1 には AppFabric 用のページング API はありません。などのバルク API はいずれも、サーバー上でクエリを実行し、一致するすべてGetObjectsByTagのキャッシュ エントリをクライアントにストリーム バックします。そこから、必要な LINQ 演算子を使用できることは明らかですが(例: )、常に完全な結果セットをサーバーから取得していることに注意してください。IEnumerableSkip/Take/Count

私は個人的に、AppFabric V2 がIQueryableIEnumerable の代わりにサポートを提供することを望んでいます。これにより、LINQ2SQL や ADO.NET EF のようにクライアントに戻る前に、サーバーに完全な要求をリモートで送信できるようになります。

今のところ、アプリケーションの機能に応じて考えられる解決策の 1 つは、アイテムをキャッシュに挿入するときに実際にある種のページングを計算できることです。各ページを表すエンティティ キーの順序付けられたリストを作成し、それらを単一のエントリとしてキャッシュに保存して、1 回の要求で取り出してから個別に (並行して) キャッシュからリスト内のアイテムを一括フェッチして結合することができます。インメモリ LINQ クエリを使用します。CPU とメモリを交換したい場合は、ID ではなく完全なエンティティの実際のリストをキャッシュし、エンティティの結合を行う必要があります。

入ってくる検索基準に基づいて、これらのオブジェクトのリストをキャッシュからすばやくプルするには、なんらかのキーイング メカニズムを考え出す必要があることは明らかです。このようなある種のキーイングがうまくいくかもしれません:

private static string BuildPageListCacheKey(string entityTypeName, int pageSize, int pageNumber, string sortByPropertyName, string sortDirection)
{
   return string.Format("PageList<{0}>[pageSize={1};pageNumber={2};sortedBy={3};sortDirection={4}]", entityTypeName, pageSize, pageNumber, sortByPropertyName, sortDirection);
}

キャッシュ エントリがまだ入力されていない場合にオンデマンドで実行してユーザーを待機させるのではなく、キャッシュを最新の状態に保つ別のプロセスまたはワーカー スレッドでこの種のことを行うことを検討することをお勧めします。

このアプローチが最終的にうまくいくかどうかは、アプリケーションとデータのいくつかの要因によって異なります。それがあなたのシナリオにぴったり合っていない場合でも、少なくとも、問題を解決するための別の考え方に心を向けるのに役立つでしょう。

于 2011-02-22T03:44:47.380 に答える