3

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

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

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

IEnumerable result= MyValues.Distinct();
4

4 回答 4

6

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

更新:LINQDistinct()调用也应该是O(n).

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

于 2012-10-01T20:58:35.793 回答
1

来自评论

我实际上使用 MyDistinct.Distinct()

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

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

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

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

LINQ 扩展方法的顺序不影响性能?

这是一个小演示,您可以在其中看到顺序很重要,但您也可以看到它并不重要,因为比较双精度对于 cpu 来说是微不足道的:

Time for first orderby then distinct: 00:00:00.0045379
Time for first distinct then orderby: 00:00:00.0013316
于 2012-10-01T21:10:20.190 回答
1

有没有更有效的方法来做到这一点?

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

于 2012-10-01T21:02:19.117 回答
0

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

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

Select <_varname> from MyDataTable order by <_varname>

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

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

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

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

希望这可以帮助

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

于 2012-10-01T21:14:27.690 回答