当我在LINQ查询中切换Distinct()和OrderBy()时,性能会发生变化吗?



我只是考虑当我在LINQ查询中同时使用OrderBy()Distinct()时,哪个为我提供了最佳性能。在我看来,它们在速度上都是相等的,因为Distinct()方法将使用哈希表,而在内存中,我假设任何SQL查询将首先由。net优化,然后再执行。
我的假设是正确的吗?还是这两个命令的顺序仍然影响LINQ的性能?
至于如何运作…当你构建一个LINQ查询时,你基本上是在构建一个表达式树,但还没有执行任何东西。所以调用MyList.Distinct().OrderBy()只会生成这个树,但不会执行它。(延期)。只有当你调用另一个函数如ToList()时,表达式树才会被执行,并且运行库可以在执行表达式树之前优化表达式树。

对于LINQ to对象,即使我们假设OrderBy(...).Distinct()Distinct().OrderBy(...)将返回相同的结果(这是不保证的),性能将取决于数据。

如果数据中有很多重复,首先运行Distinct应该会更快。下一个基准测试显示(至少在我的机器上):

public class LinqBench
{
private static List<int> test = Enumerable.Range(1, 100)
.SelectMany(i => Enumerable.Repeat(i, 10))
.Select((i, index) => (i, index))
.OrderBy(t => t.index % 10)
.Select(t => t.i)
.ToList();
[Benchmark]
public List<int> OrderByThenDistinct() => test.OrderBy(i => i).Distinct().ToList();
[Benchmark]
public List<int>  DistinctThenOrderBy()=> test.Distinct().OrderBy(i => i).ToList();
}

在我的机器上。net Core 3.1它给出:

StdDev
OrderByThenDistinct129.74 us2.120 us1.879 us
distincttheenorderby19.58 us0.384 us0.794 us

首先,seq.OrderBy(...).Distinct()seq.Distinct().OrderBy(...)不能保证返回相同的结果,因为Distinct()可能返回一个无序枚举。MS实现方便地保留了顺序,但是如果你向数据库传递一个LINQ查询,结果可能以DB引擎认为合适的任何顺序返回。

第二,在极端情况下,当你有很多重复(比如,五个值随机重复1,000,000次),你最好在OrderBy()之前执行Distinct

长话短说,如果你希望你的结果是有序的,使用Distinct().OrderBy(...)而不管性能。

我假设任何SQL查询将首先由。net优化,然后才得到>执行。

你认为这将如何工作,考虑到:

  • 只有SQL执行端(服务器)知道这一点(即使用哪些索引),并且有一个查询优化器,应该根据表的统计数据优化已执行的查询。
  • 你必须非常确定你没有以任何方式改变结果。

对不起,这没有意义——如果没有数据库的所有内部细节,c#中几乎没有可以安全地进行的优化,所以查询被发送到数据库进行分析。

因此,OrderBy或Distinct(尤其是Distinct)将影响性能——影响程度取决于OrderBy是否可以依赖索引。

或者这两个命令的顺序是否仍然影响LINQ的性能一般来说呢?

这里很有趣(你没有举例子)。

DISTINCT和ORDERBY在SQL中有特定的顺序,不管你在LINQ中是如何表述的。根据SQL定义,只有一种允许的语法。LINQ将查询放在一起并对其进行优化。如果你看一下语法,你会发现DISTINCT(至少是SQL Server的一个SQL术语)和OrderBy有一个特定的位置。

在另一边…

.Distinct () .OrderBy()和.OrderBy () .Distinct ()

有不同的结果。它们可以在SQL中完成(您可以使用Distinct的输出作为虚拟表,然后对其进行排序),但是它们具有不同的语义。除非你认为LINQ会神奇地读懂你的思想,否则编译器除了假设你有能力写出你所做的事情(只要它是合法的)并按照你给出的顺序执行这些步骤之外,没有任何上下文。

Except:在Queryable中Distinct的文档是明确的,这是不做的:

https://learn.microsoft.com/en-us/dotnet/api/system.linq.queryable.distinct?redirectedfrom=MSDN&视图=净- 5.0 # System_Linq_Queryable_Distinct__1_System_Linq_IQueryable___0__

表示Distinct返回一个无序列表。

所以,它们有一个根本的区别,它们不一样。

相关内容

  • 没有找到相关文章

最新更新