【问题标题】:LINQ c# efficiencyLINQ c# 效率
【发布时间】:2012-10-01 20:54:16
【问题描述】:

我需要编写一个查询,从用户为任何给定数据集定义的列中提取不同的值。可能有数百万行,因此语句必须尽可能高效。下面是我的代码。

这个 LINQ 查询的顺序是什么?有没有更有效的方法来做到这一点?

var MyValues = from r in MyDataTable.AsEnumerable()
               orderby r.Field<double>(_varName)
               select r.Field<double>(_varName); 

IEnumerable result= MyValues.Distinct();

【问题讨论】:

  • 确定这一点的最佳方法是在 SQL 探查器运行时运行 LINQ 查询。您可以看到实际的 SQL 查询,并据此在 SSMS 中生成执行计划。
  • “这个 LINQ 查询的顺序”是什么意思?您想知道语句按什么顺序执行吗?
  • @Pheonixblade9:实际上,通过调用AsEnumerable(),SQL 脚本非常基础。 orderbyselect 都在本地运行。
  • @L.B:我猜他的查询填充MyDataTable 正在执行GROUP BYDISTINCT;我猜上面的 LINQ 是一个 LINQ-to-Objects 查询。
  • @Pheonixblade9:Linq-To-DataSet 是 Linq-To-Objects 的子集。

标签: c# performance linq ienumerable


【解决方案1】:

我不能对AsEnumerable() 调用或字段转换说太多,但对于 LINQ 方面,orderby 是一种稳定的快速排序,应该是O(n log n)。如果我不得不猜测,除了orderby 之外的所有内容都应该是O(n),所以总的来说你仍然只是O(n log n)

更新:LINQ Distinct() 调用也应该是 O(n)

所以总的来说,这个东西的 Big-Oh 仍然是 O(Kn log n),其中 K 是某个常数。

【讨论】:

    【解决方案2】:

    有没有更有效的方法?

    如果将排序作为初始化 MyDataTable 的查询的一部分进行,而不是事后在内存中排序,则效率会更高。

    【讨论】:

      【解决方案3】:

      来自 cmets

      我实际上使用 MyDistinct.Distinct()

      如果您想要不同的_varName 值并且您不能在dbms 中的选择查询中完成所有这些操作(什么是最有效的方法),您应该在OrderBy 之前使用Distinct。这里的顺序很重要。

      在开始过滤重复项之前,您需要对所有数百万行进行排序。如果您先使用 distinct,则只需订购其余部分。

      var values = from r in MyDataTable.AsEnumerable()
                   select r.Field<double>(_varName);
      IEnumerable<double> orderedDistinctValues = values.Distinct()
                                                        .OrderBy(d => d);
      

      我最近问了一个相关问题,E.Lippert 在订单重要和不重要时给出了很好的解释:

      Order of LINQ extension methods does not affect performance?

      Here's a little demo 在这里您可以看到顺序很重要,但您也可以看到它并不重要,因为比较双精度对于 cpu 来说是微不足道的:

      Time for first orderby then distinct: 00:00:00.0045379
      Time for first distinct then orderby: 00:00:00.0013316
      

      【讨论】:

      • 如果可能的话,能否提供一个基于我的 LINQ 查询的代码示例?
      • @sammarcow:编辑了我的答案以提供示例和测量结果。
      【解决方案4】:

      如果您想要所有数百万条记录并且您在 64 位内存寻址操作系统上有足够的内存,那么您的上述查询 (linq) 就很好。

      查询的顺序是,如果你看到底层命令,将被转换为

      Select <_varname> from MyDataTable order by <_varname>
      

      这与在数据库 IDE 或命令行上运行时一样好。

      给你一个关于性能的简短回答

      1. 如果可以的话,加入 where 子句(使用索引的列)
      2. 确保用户可以选择已编入索引的列 (_varname)。想象一下,数据库试图在一个未索引的列上对数百万条记录进行排序,这显然很慢,但会危及 linq 接收 badpress
      3. 确保(如果可能)使用有价值的记录正确完成 MyDataTable 的初始化(同样基于 where 子句)
      4. 分析您的基础查询,
      5. 如果可能,创建存储过程(值得商榷)。您也可以创建一个包含存储过程的实体模型

      今天可能会更快,但是随着表空间的增长,如果您的数据没有被排序(索引),那么事情会变得更慢(即使您有一个很好的 linq 表达式)

      希望对你有帮助

      也就是说,如果您的数据库未正确索引,则意味着

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-16
        • 1970-01-01
        相关资源
        最近更新 更多