2017-05-11 8 views
1

私は二度どのグループのデータのクエリを持っています:GROUPBY GROUPBYおよびすべての()のパフォーマンス内部

var query = (from a in Context.SetA() 
from b in Context.SetB().Where(x => x.aId == a.Id) // 1-to-many 
from c in Context.SetC().Where(x => x.bId == b.Id) // 1-to-many 
group new {...} by new {...} into g 
select new 
{ 
    g.Key.X, 
    g.Key.Y, 
    g.Sum(x => x....), // etc, lots of Sums 
}); 

from (q in query 
group q by true 
select new 
{ 
    g.Key.Z, 
    g.Sum(x => x.....), // etc, lots of Sums 
}); 

このすべてがうまく機能、およびパフォーマンスが許容可能です。今度は、両方のグループにAll(またはAny、差はありません)を追加すると、

パフォーマンスが大幅に低下します。 10倍速になり、5秒から50秒になります。数字は正確ではなく、ちょうどアイデアを得るためです。

私は1対多の関係が3つあり、すべてのレベル(親の合計、子の合計、孫の合計)でサマリーを行っているので、2回グループ化しています。

パフォーマンス向上のために何ができるでしょうか?

+0

おそらく、「フラグ」をカバーしないマルチフィールドインデックスのインデックスがあります。これを確認するには、EFによって生成されたさまざまなクエリのクエリ実行計画を分析する必要があります。 – xanatos

答えて

4

グルーピングに適用されるAll/Anyにマッピングできる自然なSQL GROUP BY集計がないため、EF SQL変換が非効率的であるという問題があります。

解決策は、その等価物を使用することです。

ので、代わりに

g.All(x => x.Flag) 

のように使用でき

g.Min(x => x.Flag ? 1 : 0) == 1 

それぞれ

g.Any(x => x.Flag) 

g.Max(x => x.Flag ? 1 : 0) == 1 
に置き換えることができます

更新:奇妙なことに、EFは2 MIN/MAXを生成します。末尾に(== 1の後に)反直感を付け加えることで修正されます? true : false

+0

ありがとうIvan、Minはパフォーマンスを大幅に改善しました。上記のコードから誰かがコピー/貼り付けをした場合、x.Flag? 0:1はx.Flagですか? 1:0. – Goran

+0

あなたは歓迎です:)答えは正しい表現で修正しました。それを指摘してくれてありがとう! –

関連する問題