groupby in groupby和All()性能

时间:2017-05-11 09:22:55

标签: c# sql-server linq linq-to-entities

我有一个将数据分组两次的查询:

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,没有任何区别)

g.All(x => x.Flag)
性能急剧下降。它变得慢了10倍,从5s变为50s。数字不准确,只是为了得到这个想法。

我正在进行两次分组,因为我有三个级别的1对多关系,并且我在所有级别上做总结(父级的总和,子级的总和以及孙子的值的总和)。

我有什么想法可以提高绩效?

1 个答案:

答案 0 :(得分:4)

问题是没有自然的SQL GROUP BY聚合可以映射到应用于分组的All / Any,因此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

来解决此问题