为什么IEnumerable比IQueryable更快?

3

简介

我一直在研究它们之间的区别。我决定亲自动手测试它们,因为我想看看它们之间的性能差异(如果有的话),并理解其中的原因。

我创建了一个简单的控制台应用程序。我使用Entity Framework和SQL Server。我创建了一个模型,指向一个数据库表。这个表有约1000条记录。

测试结果

Dim _db As New SampleEntities
Dim sw As New Stopwatch

测试1 - 966毫秒

Dim allMemos As IEnumerable(Of Memo) = _db.Memos
sw.Start()
allMemos.ToList()
sw.Stop()

测试2-6ms

Dim iEnum As IEnumerable(Of Memo) = _db.Memos.AsEnumerable
sw.Restart()
iEnum.Where(Function(f) f.Active).ToList()
sw.Stop()

测试3 - 186毫秒

Dim iQuer As IQueryable(Of Memo) = _db.Memos.AsQueryable
sw.Restart()
iQuer.Where(Function(f) f.Active).ToList()
sw.Stop()

我的发现

在开始之前,我的研究告诉我,在许多情况下,使用IQueryable会更快,因为它有可能优化查询,使得过滤器(例如memo是Active)由SQL执行,并且当调用ToList()时返回的结果非常少。

然而,我的发现却证明了相反的结论。为什么?我确信在我的测试中,IQueryable 应该更快。我特意设置了这个来证明。

“这是因为你使用了 IQueryable(Of Memo)!”

我也这样想。我听说将我的对象强制转换为IQueryable可能不好,因为它仍然需要从IEnumerable进行转换。所以我尝试了这个:

Dim iQuer As IEnumerable(Of Memo) = _db.Memos.AsQueryable

这确实提高了性能,所以测试 3只需要17ms就完成了,而不是186ms。但它仍然比测试 2的6ms要慢。

这是怎么回事呢?


2
小伙子,人们将会对你的“性能”测试大谈特谈。做好准备。 - AMissico
没关系,这就是我学习的方式 :D - Rowan Freeman
3
我建议你再试一下,加入几百万行数据。使用1000行数据进行性能测试并不具备充分的性能测试条件。 - qujck
这是真的,并且在一定程度上回答了我的问题,即“我做错了什么?” - Rowan Freeman
1个回答

2
我不知道_db.Memos返回的内容,但在测试2中。
Dim iEnum As IEnumerable(Of Memo) = _db.Memos.AsEnumerable

所有记录可以一次性加载到内存中。

在测试3中,当您调用ToList时,记录将被加载:

  iQuer.Where(Function(f) f.Active).ToList()

你需要做两件事:

  1. 在赋值之前移动计时器行,并比较结果。
  2. 设置数据库跟踪以查看代码实际访问数据库的位置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接