3

最近、SQL Server2008に対するEntityFrameworkクエリでパフォーマンスの問題が発生しました。問題を修正できましたが、修正が機能した理由がわかりません。.Contains()メソッドを使用してGuidのコレクションを使用して、SQLでIN句を生成しています。元のコードは次のとおりです(無実を保護するためにテーブル名が変更されています)。

Guid[] values = filter.Split(',').Select<String, Guid>(d => new Guid(d)).ToArray();


returnValue = returnValue.Where(t => values.Contains(t.WorkItem.Requirement.Project.ProjectId));

ProjectIDが150を超える場合、このクエリの実行には最大20秒かかります。.Contains()の場所を変更することで、処理を大幅に高速化できます。リファクタリングは次のとおりです。

Guid[] values = filter.FilterValue.Split(',').Select<String, Guid>(d => new Guid(d)).ToArray();

var projects = from p in context.DC_DEF_Project
               where values.Contains(p.ProjectId)
               select p;

returnValue = from t in returnValue
              join p in projects on t.DC_DEF_ProjectWorkItem.DC_DEF_ProjectRequirement.ProjectId equals p.ProjectId
              select t;

このコードは、上記のクエリと同じデータセットで約0.125秒かかります。

これには確かな理由があると思いますが、私の好奇心は私を殺しています。それは何ですか?

4

3 に答える 3

1

私の推測では、最初の1つは、2番目の結合が主キーによってプロジェクトにマッハし、150のIDを1回だけ評価してから、それを他のテーブル。

于 2012-06-25T19:48:47.327 に答える
0

最初の例では、データセット全体をアプリに取り込み、それに対してメモリ内のlinqクエリを実行していると思います。

于 2012-06-25T19:42:23.430 に答える
0

Linqの動作を理解している限り、クエリの実行の延期と関係があるはずです。

固定バージョンでは、2つのLinq式が次々に評価および解釈されますが、結果を列挙するときに1回だけ実行されます(存在する場合)。これにより、データベースアクセスが適切に削減されます

最初のバージョン:

returnValue.Where(t => values.Contains(t.WorkItem.Requirement.Project.ProjectId))

最初のステップではフィルタリングを行いません。現在のテーブル行のがテーブルのすべてProjectIdの行に含まれているかどうかをチェックします!values

于 2012-06-25T19:48:01.297 に答える