LINQ执行时间

时间:2014-09-17 13:26:27

标签: c# linq

今天我注意到当我在大数据上运行几个LINQ语句时,所花费的时间可能会有很大差异。

假设我们有这样的查询:

var conflicts = features.Where(/* some condition */);           
foreach (var c in conflicts) // log the conflicts

其中features是表示表中行的对象列表。因此,这些对象非常复杂,甚至查询它们的一个简单属性是一个巨大的操作(包括实际的数据库查询,验证,状态更改......)我认为执行这样的查询需要很长时间。错误:第一个语句在很短的时间内执行,而简单地循环结果则是永恒的。

但是,如果我使用IEnumerable#ToList()将LINQ表达式检索的集合转换为List,则第一个语句运行稍慢并且循环结果非常快。话虽如此,第二次接近的完整持续时间远小于不转换为列表时的持续时间。

var conflicts = features.Where(/* some condition */).ToList();           
foreach (var c in conflicts) // log the conflicts

所以我认为var conflicts = features.Where实际上并不查询,而是准备数据。但我不明白为什么转换到列表然后循环比这快得多。 这是实际问题

有人对此有解释吗?

2 个答案:

答案 0 :(得分:5)

本声明,只是声明你的意图:

var conflicts = features.Where(...);

获取满足Where子句中条件的数据。然后当你写这个

foreach (var c in conflicts) 

将执行实际查询并开始获取结果。这称为lazy loading。我们用于此的另一个术语是默认执行。我们不断执行查询,直到我们需要它的数据。

另一方面,如果你做过这样的事情:

var conflicts = features.Where(...).ToList(); 

将创建一个内存集合,其中将存储查询结果。在这种情况下,查询将立即执行。

一般来说,正如您在维基百科中读到的那样:

  

延迟加载是计算机编程中常用的设计模式   将对象的初始化推迟到它所在的点   需要。如果,它可以提高程序操作的效率   适当和适当使用。与延迟加载相反的是渴望   负荷。

<强>更新

  

我认为这种内存中的集合比起来时要快得多   懒加载?

Here是一篇很棒的文章,可以回答您的问题。

答案 1 :(得分:0)

欢迎来到懒惰评价的精彩世界。使用LINQ,在需要结果之前不会执行查询。在尝试获取结果之前(ToList()获取结果并将其放入列表中)您只是创建查询。将其视为编写代码与运行程序。虽然这可能令人困惑,并且可能导致代码在意外时间执行,甚至多次执行,例如,如果您将查询提前两次,这实际上是一件好事。它允许您拥有一段返回查询的代码(不是结果而是实际查询),并让另一段代码根据原始查询创建一个新查询。例如,您可以在原件上添加其他过滤器或将其分页。

您看到的性能差异基本上是代码中不同位置发生的数据库调用。