かなり大きなクエリを実行し、多くの結合などを実行するコードがあります。簡単にするために、多かれ少なかれ構造を次に示します。
var rootQuery = MainQuery(); // IQueryable<MyClass>
var jq1 = JoinQuery1(); // IQueryable<anonymous type>
var jq2 = JoinQuery2();
...
var jq6 = JoinQuery6();
var bigQuery = from x in rootQuery
join j1 in jq1 on x.ID equals j1.MainID into join1
from j1 in join1.DefaultIfEmpty()
join j2 in jq2 on x.ID equals j2.MainID into join2
from j2 in join1.DefaultIfEmpty()
...
join j6 in jq6 on x.ID equals j6.MainID into join6
from j6 in join1.DefaultIfEmpty()
select new {
x.ID,
x.Field1,
j1.FieldA,
j2.FieldB,
...
j6.FieldF
};
var sw = Stopwatch.StartNew();
var loadedData = bigQuery.ToList();
sw.Stop();
Console.WriteLine("Time Elapsed = {0} ms", sw.ElapsedMilliseconds);
ストップウォッチは 30 秒以上の経過を示しており、9 行と約 30 列のデータ (テキスト フィールドなし) を返しています。そのため、SQL Server Profiler を使用してクエリを盗聴しましたが、実際には怪物です。いくつかのインデックスをいじったり、突っ込んだり、最適化したりして、クエリを 200 ミリ秒未満で実行することができました。しかし、コードを実行する.ToList()
と、クエリ部分が 200 ミリ秒未満であると SQL Profiler が言っているにもかかわらず、実行に30 秒以上かかっています。
ここで何が起こっているのですか?.ToList がこのような小さなデータ セットをメモリに読み込むのに時間がかかるのはなぜですか?
編集:問題を回避しました(以下の回答を参照)が、満足していません。より良い方法を提案できる人、または少なくともオブジェクトの実体化が非常に高価である理由を説明して、7 つの個別のクエリを実行し、それらをローカル メモリに結合する方が安く済む理由を説明してください。