基本上,正如问题所述...... LINQ函数的顺序是否在性能方面很重要?显然结果仍然必须相同......
示例:
myCollection.OrderBy(item => item.CreatedDate).Where(item => item.Code > 3);
myCollection.Where(item => item.Code > 3).OrderBy(item => item.CreatedDate);
两者都返回相同的结果,但是处于不同的LINQ顺序。我意识到重新排序某些项目会产生不同的结果,我并不关心这些。我主要关心的是,在获得相同结果时,排序是否会影响性能。而且,不只是在我做的2个LINQ调用(OrderBy,Where),而是在任何LINQ调用上。
答案 0 :(得分:143)
这取决于使用的LINQ提供程序。对于LINQ to Objects,这肯定会产生巨大的差异。假设我们实际上得到了:
var query = myCollection.OrderBy(item => item.CreatedDate)
.Where(item => item.Code > 3);
var result = query.Last();
这需要对整个集合进行排序,然后然后过滤。如果我们有一百万个项目,其中只有一个项目的代码大于3,那么我们就会浪费大量时间来排序将丢弃的结果。
将其与反向操作进行比较,先过滤:
var query = myCollection.Where(item => item.Code > 3)
.OrderBy(item => item.CreatedDate);
var result = query.Last();
这次我们只是对过滤后的结果进行排序,在“只有一个与过滤器匹配的项目”的示例中,它将在时间和空间上更加高效。
考虑:
var query = myCollection.Where(item => item.Code != 0)
.OrderBy(item => 10 / item.Code);
var result = query.Last();
没关系 - 我们知道我们永远不会除以0.但如果我们在过滤之前执行排序,查询将抛出异常。
答案 1 :(得分:17)
是
但 的性能差异究竟取决于LINQ提供程序如何评估基础表达式树。
例如,对于LINQ-to-XML,您的查询可能第二次执行得更快(首先使用WHERE子句),但第一次执行LINQ-to-SQL时更快。
要准确了解性能差异,您很可能想要分析您的应用程序。尽管如此,过早优化通常不值得努力 - 您可能会发现LINQ性能以外的问题更为重要。
答案 2 :(得分:5)
在您的特定示例中,可以对性能产生影响。
首次查询:您的OrderBy
调用需要遍历整个源序列,包括Code
为3或更少的项目。然后Where
子句还需要迭代整个有序序列。
第二个查询:Where
调用仅将序列限制为Code
大于3的项。OrderBy
调用只需要遍历{返回的减少的序列{1}}致电。
答案 3 :(得分:3)
在Linq-To-Objects中:
排序相当慢并使用O(n)
内存。另一方面,Where
相对较快并且使用恒定的内存。因此,首先执行Where
会更快,而对于大型集合则要快得多。
内存压力降低也很大,因为根据我的经验,大对象堆上的分配(连同它们的集合)相对昂贵。
答案 4 :(得分:1)
显然结果必须相同......
请注意,实际上并非如此 - 特别是,以下两行将给出不同的结果(对于大多数提供者/数据集):
myCollection.OrderBy(o => o).Distinct();
myCollection.Distinct().OrderBy(o => o);
答案 5 :(得分:1)
值得注意的是,在考虑如何优化LINQ查询时应该小心。例如,如果使用LINQ的声明版本执行以下操作:
public class Record
{
public string Name { get; set; }
public double Score1 { get; set; }
public double Score2 { get; set; }
}
var query = from record in Records
order by ((record.Score1 + record.Score2) / 2) descending
select new
{
Name = record.Name,
Average = ((record.Score1 + record.Score2) / 2)
};
如果出于某种原因,您决定首先将平均值存储到变量中来“优化”查询,那么您将无法获得所需的结果:
// The following two queries actually takes up more space and are slower
var query = from record in Records
let average = ((record.Score1 + record.Score2) / 2)
order by average descending
select new
{
Name = record.Name,
Average = average
};
var query = from record in Records
let average = ((record.Score1 + record.Score2) / 2)
select new
{
Name = record.Name,
Average = average
}
order by average descending;
我知道没有多少人使用声明性LINQ作为对象,但它是一些值得思考的好东西。
答案 6 :(得分:0)
这取决于相关性。假设您的Code = 3的项目非常少,那么下一个订单将适用于小型集合,以便按日期获取订单。
如果您有许多具有相同CreatedDate的项目,那么下一个订单将适用于更大的集合集合以按日期获取订单。
因此,在这两种情况下,性能都会有所不同