3

このクエリを最適化する方法は?

// This will return data ranging from 1 to 500,000 records
List<string> products = GetProductsNames(); 


List<Product> actualProducts = (from p in db.Products
                               where products.Contains(p.Name)
                               select p).ToList();

44,000 個の文字列のリストを送信した場合、このコードの入力には約 30 秒かかりますactualProducts。500,000 レコードの場合はわかりません。:(

このクエリを微調整する方法はありますか?

注: 呼び出しごとにほぼ同じ時間がかかります (最初の遅い edmx 呼び出しを無視します)。

4

3 に答える 3

4

500,000 レコードに対するINクエリは、常に病的なケースになります。

まず、データベースにインデックス (おそらくクラスター化されていない) があることを確認Nameします。

アイデア (どちらも ADO.NET への移行を伴います):

  • 「テーブル値パラメーター」を使用して値を渡し、INNER JOINTSQL のテーブル値パラメーターに渡す
  • ProductQueryまたは、列QueryId(​​ の場合もありますuniqueidentifier) とName;を含むフォームのテーブルを作成します。クエリを表す guid を作成し ( Guid.NewGuid())、SqlBulkCopy500,000 ペア (各行で同じ guid。異なる guid は異なるクエリ) を非常に迅速にテーブルにプッシュします。次に、TSQLを使用しINNER JOINて2つのテーブル間で実行します

実際、これらは非常に似ていますが、最初のものはおそらく最初に試すものです. 設定することが少なくなります。

于 2013-07-20T20:04:59.303 に答える
1

データベースを使用したくない場合は、何かを試すことができますDictionary<string,string>

間違っていなければproducts.Contains(p.Name)、O(n) 操作であるため、コストがかかると思われます。GetProductsNames戻り値の型を asに変更するDictionary<string,string>か、List を Dictionary に変換してみてください

Dictionary<string, string> productsDict = products.ToDictionary(x => x);

辞書が手元にあるので、次のようにクエリを書き直します

List<Product> actualProducts = (from p in db.Products
                           where productsDict.ContainsKey(p.Name)
                           select p).ToList();

これは、パフォーマンスを大幅に向上させるのに役立ちます (欠点は、2 倍のメモリを割り当てることです。利点はパフォーマンスです)。非常に大きなサンプルでテストを行い、良好な結果が得られました。やってみて。

お役に立てれば。

于 2013-07-20T20:26:57.967 に答える