当我在 LINQ 查询中切换 Distinct() 和 OrderBy() 时,性能会发生变化吗?
Does the performance change when I switch Distinct() and OrderBy() in a LINQ Query?
我只是在考虑当我在 LINQ 查询中同时使用 OrderBy()
和 Distinct()
时哪个能为我提供最佳性能。在我看来,它们在速度上是相等的,因为 Distinct()
方法将在内存中使用散列 table,我假设任何 SQL 查询将首先由 .NET 优化在它被执行之前。
我的假设是否正确,或者这两个命令的顺序是否仍然影响 LINQ 的总体性能?
至于它是如何工作的……当您构建 LINQ 查询时,您基本上是在构建表达式树,但尚未执行任何操作。所以调用 MyList.Distinct().OrderBy()
只会生成这棵树,但不会执行它。 (它是延迟的。)只有当你调用另一个函数时 ToList()
才会执行表达式树,并且运行时可以在执行之前优化表达式树。
首先,seq.OrderBy(...).Distinct()
和seq.Distinct().OrderBy(...)
不能保证return相同的结果,因为Distinct()
may return an unordered enumeration。 MS 实现可以方便地保留顺序,但如果您将 LINQ 查询传递给数据库,结果可能会以数据库引擎认为合适的任何顺序返回。
其次,在出现大量重复的极端情况下(例如,五个值随机重复 1,000,000 次),您最好在 OrderBy()
.[=17= 之前执行 Distinct
]
长话短说,如果您希望对结果进行排序,请使用 Distinct().OrderBy(...)
而不管性能如何。
对于 LINQ to 对象,即使我们假设 OrderBy(...).Distinct()
和 Distinct().OrderBy(...)
将 return 相同的结果 (which is not guaranteed),性能也将取决于数据。
如果您有很多重复数据 - 运行 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 机器上它给出:
Method
Mean
Error
StdDev
OrderByThenDistinct
129.74 us
2.120 us
1.879 us
DistinctThenOrderBy
19.58 us
0.384 us
0.794 us
I assume that any SQL query would be optimized first by .NET before it gets >
executed.
鉴于以下情况,您认为这将如何运作:
- 只有 SQL 执行端(服务器)知道这方面的知识(即使用哪些索引)并且有一个查询优化器应该根据 SQL 的统计信息优化执行的查询=50=].
- 您必须非常确定您不会以任何方式更改结果。
抱歉,这没有意义 - 在没有数据库的所有内部细节的情况下,您几乎无法在 C# 中安全地进行优化,因此将查询发送到数据库进行分析。
因此,OrderBy 或 Distinct(特别是不同的)会影响性能 - 多少取决于 OrderBy 是否可以依赖索引。
or does the order of these two commands still affect the performance of LINQ
in general?
这里很有趣(而且你没有举出例子)。
DISTINCT 和 ORDERBY 在 SQL 中以特定顺序排列,无论您在 LINQ 中如何制定它。根据 SQL 定义,只有一种允许的语法。 LINQ 将查询放在一起并对其进行优化。如果您查看语法,DISTINCT(至少是 SQL 服务器的 SQL 术语)和 OrderBy 有一个特定的位置。
另一边...
.Distinct().OrderBy() 和 .OrderBy().Distinct()
有不同的结果。它们可以在 SQL 中完成(您可以将 Distinct 的输出用作虚拟 table 然后您可以订购),但它们具有不同的语义。除非你认为 LINQ 会神奇地读懂你的想法,否则编译器除了假设你有能力编写你所做的事情(只要它是合法的)并按照你给出的顺序执行这些步骤之外没有任何上下文。
例外:可查询中 Distinct 的文档很清楚,这还没有完成:
表示 Distinct returns 是一个无序列表。
因此,它们之间存在根本区别,并不相同。
我只是在考虑当我在 LINQ 查询中同时使用 OrderBy()
和 Distinct()
时哪个能为我提供最佳性能。在我看来,它们在速度上是相等的,因为 Distinct()
方法将在内存中使用散列 table,我假设任何 SQL 查询将首先由 .NET 优化在它被执行之前。
我的假设是否正确,或者这两个命令的顺序是否仍然影响 LINQ 的总体性能?
至于它是如何工作的……当您构建 LINQ 查询时,您基本上是在构建表达式树,但尚未执行任何操作。所以调用 MyList.Distinct().OrderBy()
只会生成这棵树,但不会执行它。 (它是延迟的。)只有当你调用另一个函数时 ToList()
才会执行表达式树,并且运行时可以在执行之前优化表达式树。
首先,seq.OrderBy(...).Distinct()
和seq.Distinct().OrderBy(...)
不能保证return相同的结果,因为Distinct()
may return an unordered enumeration。 MS 实现可以方便地保留顺序,但如果您将 LINQ 查询传递给数据库,结果可能会以数据库引擎认为合适的任何顺序返回。
其次,在出现大量重复的极端情况下(例如,五个值随机重复 1,000,000 次),您最好在 OrderBy()
.[=17= 之前执行 Distinct
]
长话短说,如果您希望对结果进行排序,请使用 Distinct().OrderBy(...)
而不管性能如何。
对于 LINQ to 对象,即使我们假设 OrderBy(...).Distinct()
和 Distinct().OrderBy(...)
将 return 相同的结果 (which is not guaranteed),性能也将取决于数据。
如果您有很多重复数据 - 运行 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 机器上它给出:
Method | Mean | Error | StdDev |
---|---|---|---|
OrderByThenDistinct | 129.74 us | 2.120 us | 1.879 us |
DistinctThenOrderBy | 19.58 us | 0.384 us | 0.794 us |
I assume that any SQL query would be optimized first by .NET before it gets > executed.
鉴于以下情况,您认为这将如何运作:
- 只有 SQL 执行端(服务器)知道这方面的知识(即使用哪些索引)并且有一个查询优化器应该根据 SQL 的统计信息优化执行的查询=50=].
- 您必须非常确定您不会以任何方式更改结果。
抱歉,这没有意义 - 在没有数据库的所有内部细节的情况下,您几乎无法在 C# 中安全地进行优化,因此将查询发送到数据库进行分析。
因此,OrderBy 或 Distinct(特别是不同的)会影响性能 - 多少取决于 OrderBy 是否可以依赖索引。
or does the order of these two commands still affect the performance of LINQ in general?
这里很有趣(而且你没有举出例子)。
DISTINCT 和 ORDERBY 在 SQL 中以特定顺序排列,无论您在 LINQ 中如何制定它。根据 SQL 定义,只有一种允许的语法。 LINQ 将查询放在一起并对其进行优化。如果您查看语法,DISTINCT(至少是 SQL 服务器的 SQL 术语)和 OrderBy 有一个特定的位置。
另一边...
.Distinct().OrderBy() 和 .OrderBy().Distinct()
有不同的结果。它们可以在 SQL 中完成(您可以将 Distinct 的输出用作虚拟 table 然后您可以订购),但它们具有不同的语义。除非你认为 LINQ 会神奇地读懂你的想法,否则编译器除了假设你有能力编写你所做的事情(只要它是合法的)并按照你给出的顺序执行这些步骤之外没有任何上下文。
例外:可查询中 Distinct 的文档很清楚,这还没有完成:
表示 Distinct returns 是一个无序列表。
因此,它们之间存在根本区别,并不相同。