LINQ执行时间

本文关键字:执行时间 LINQ | 更新日期: 2023-09-27 18:22:08

今天我注意到,当我在大数据上运行几个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实际上并不查询,而是准备数据。但我不明白为什么转换成列表然后循环要快得多这才是真正的问题

有人对此作出解释吗?

LINQ执行时间

这句话,只是声明你的意图:

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

得到符合CCD_ 4子句条件的数据。然后当你写这个

foreach (var c in conflicts) 

实际的查询将被执行,并将开始获取结果。这被称为lazy loading。我们对此使用的另一个术语是deffered execution。我们定义查询的执行,直到我们需要它的数据。

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

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

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

一般来说,正如你在维基百科上看到的那样:

懒惰加载是计算机编程中常用的一种设计模式将对象的初始化推迟到它所在的点需要。如果正确和适当地使用。懒惰加载的反面是渴望加载。

更新

我想这种内存中的收集要比执行时快得多惰性负载?

这是一篇很好的文章,回答了你的问题。

欢迎来到懒惰评价的奇妙世界。使用LINQ,在需要结果之前不会执行查询。在您尝试获取结果(ToList()获取结果并将其放入列表中)之前,您只是在创建查询。可以把它看作是编写代码和运行程序。虽然这可能会令人困惑,并可能导致代码在意外的时间执行,甚至多次执行,例如,如果您对查询进行了两次foreach,这实际上是一件好事。它允许您有一段返回查询(不是结果,而是实际查询)的代码,并让另一段代码基于原始查询创建新查询。例如,您可以在原始文件或页面上添加额外的过滤器。

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