gpt4 book ai didi

c# - LINQ 嵌套组性能

转载 作者:太空宇宙 更新时间:2023-11-03 23:43:37 25 4
gpt4 key购买 nike

我有一个从 sql compact 数据库中提取数据的完整外部联接查询(我使用 EF6 进行映射):

        var query =
from entry in left.Union(right).AsEnumerable()
select new
{
...
} into e
group e by e.Date.Year into year
select new
{
Year = year.Key,
Quartals = from x in year
group x by (x.Date.Month - 1) / 3 + 1 into quartal
select new
{
Quartal = quartal.Key,
Months = from x in quartal
group x by x.Date.Month into month
select new
{
Month = month.Key,
Contracts = from x in month
group x by x.Contract.extNo into contract
select new
{
ExtNo = month.Key,
Entries = contract,
}
}
}
};

如您所见,我使用嵌套组来构建结果。有趣的是,如果我删除 AsEnumerable() 调用,查询将花费 3.5 倍的时间来执行:~210ms vs ~60ms。当它第一次运行时,差异要大得多:39000(!)ms 与 1300ms。

我的问题是:

  1. 我做错了什么,也许这些分组应该以不同的方式完成?

  2. 为什么第一次执行要花这么多时间?我知道应该构建表达式树等,但 39 秒?

  3. 在我的案例中,为什么 linq to db 比 linq to entities 慢?如果可能的话,在处理之前从数据库加载数据通常更慢并且更好吗?

谢谢!

最佳答案

回答你的三个问题:

Maybe those groupings should be done in a different way?

没有。如果您想要嵌套分组,您只能通过分组内的分组来实现。

可以一次按多个字段分组:

from entry in left.Union(right)
select new
{
...
} into e
group e by new
{
e.Date.Year,
Quartal = (e.Date.Month - 1) / 3 + 1,
e.Date.Month,
contract = e.Contract.extNo
} into grp
select new
{
Year = grp.Key,
Quartal = grp.Key,
Month = grp.Key,
Contracts = from x in grp
select new
{
ExtNo = month.Key,
Entries = contract,
}
}

这将从生成的查询中消除很多复杂性,因此它可能会(大大)更快没有 AsEnumerable()。但结果却大不相同:扁平组(年、季度等,在一行中),而不是嵌套分组。

  1. Why the first execution takes so much time?

因为生成的 SQL 查询可能非常复杂,数据库引擎的查询优化器找不到快速执行路径。

3a. Why is linq to db slower than linq to entities in my case?

因为,显然,在这种情况下,首先将数据提取到内存中并通过 LINQ-to-objects 进行分组效率要高得多。如果 leftright 代表或多或少复杂的查询本身,这种效果将更加显着。在那种情况下,生成的 SQL 会变得非常臃肿,因为它必须在一个语句中处理两个复杂来源,这可能会导致许多重复的相同子查询。通过外包分组,数据库可能只剩下相对简单的查询,当然内存中的分组永远不会受到 SQL 查询复杂性的影响。

3b. Is it generally slower and its better to load data from db if possible before processing?

不,一般不会。我什至会说,几乎没有。在这种情况下,这是因为(如我所见)您没有过滤数据。但是,如果 AsEnumerable() 之前的部分将返回数百万条记录,并且您将在之后应用过滤,则没有 AsEnumerable() 的查询可能会快得多,因为过滤是在数据库中完成。

因此,您应该始终关注生成的 SQL。期望 EF 总是生成 super 优化的 SQL 语句是不现实的。它几乎永远不会。它的主要重点是正确性(并且它在这方面做得非常出色),性能是次要的。让 LINQ-to-Entities 和 LINQ-to-object 作为一个巧妙的团队一起工作是开发人员的工作。

关于c# - LINQ 嵌套组性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28234940/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com