【问题标题】:Why is this LINQ IQueryable Performance for Pagination so poor?为什么分页的 LINQ IQueryable 性能如此差?
【发布时间】:2013-11-20 01:35:25
【问题描述】:
List<Device> deviceList = GetDevices(); // these are loaded in memory already as a list

IQueryable<Device> IDevices = deviceList.AsQueryable<Device>();

deviceList = IDevices.Where(i => i.StatusID == 2).OrderBy(j => j.LastCommunicated).Skip(recordsToSkip).Take(pageSize).ToList();

鉴于上面的代码,我在列表中大约有 1000 个设备被查询。第三个语句很慢。如果它已经加载到内存中,它不应该很快吗?我知道在大多数情况下,您会将整个查询应用于数据库调用,但在我的情况下,我已经将设备加载到内存中。第一次和第二次通话非常快。

【问题讨论】:

  • 非常慢到底是什么意思?你能发布你的测量结果吗?更好的是,你能发布分析代码的结果吗?
  • 该调用不应“非常慢”。不是该列表中只有 1000 个项目。 StatusID 或 LastCommunicated CPU 密集吗?返回 4 个迭代器本身不应该是一个问题。 Take 和 skip 是(根据我的直觉和组装知识)非常快速的操作。
  • @Dave,请不要将您的问题改写为“我现在明白了”。这将帮助 0 个未来的用户。

标签: c# performance linq iqueryable


【解决方案1】:

IQueryable 在这一点上无关紧要。您看到的性能问题是每个链都返回一个新的迭代器。

所以,这个:

IDevices
    .Where(i => i.StatusID == 2) // iterates over 1000 items
    .OrderBy(j => j.LastCommunicated) // orders however many items have a StatusID of 2
    .Skip(recordsToSkip) // iterates "recordsToSkip" number of times
    .Take(pageSize) // iterates "pageSize" times

是一个循序渐进的过程。首先,Where 执行。这会遍历整个列表。然后OrderBy 执行,你可以想象这是相当密集的。 Skip 然后迭代直到找到您想要的索引。 Take 然后在您形成新列表之前迭代 n 个项目。

话虽如此.. 如果您直接对数据库运行此查询,它会快得多。

【讨论】:

  • 我明白了。我想既然数据已经在内存中,我可以快速对其进行排序。
  • "每个链返回一个新列表" - 这是不正确的 - 每个链返回一个新的 迭代器
  • @DStanley 道歉。固定。
  • 您可能应该考虑再次从 db 中获取数据,即使您的内存中已经有整个表。办公室。如果是 db 相关案例。
  • @Dave 您永远无法编写与具有各种索引功能的数据库的速度相匹配的代码(除非您自己实现它们)。在内存集合上使用 LINQ 时尤其如此。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-27
  • 2012-10-18
  • 2012-11-29
相关资源
最近更新 更多