简体   繁体   English

使用LINQ时谓词的顺序是否重要?

[英]Is order of the predicate important when using LINQ?

I understand that executing operations in different orders will yield different performance such as the difference between the following slow query: 我理解以不同的顺序执行操作会产生不同的性能,例如以下慢查询之间的差异:

List<TestItem> slowResults = items.OrderBy(item => item.StringItem)
                                  .Where(item => item.IntItem == 100)
                                  .ToList();

and this faster one: 这个更快的一个:

List<TestItem> fastResults = items.Where(item => item.IntItem == 100)
                                  .OrderBy(item => item.StringItem)
                                  .ToList();

But that is not my question: 但这不是我的问题:

My question is about performance of the short circuiting as it relates to a LINQ predicate. 我的问题是关于短路的性能,因为它与LINQ谓词有关。 When I use a Where clause, like in this case: 当我使用Where子句时,就像在这种情况下:

List<TestItem> results = items.Where(item => item.Item1 == 12 &&
                                             item.Item2 != null &&
                                             item.Item2.SubItem == 65 &&
                                             item.Item3.Equals(anotherThingy))
                              .ToList();

Doesn't the order of the arguments matter? 参数的顺序不重要吗? For instance, I would expect that doing a .Equals first would result in a slower query overall due to the Item1 == 12 integer evaluation being a much faster operation? 例如,我会期望首先执行.Equals会导致整体查询速度变慢,因为Item1 == 12整数评估是一个更快的操作?

If order does matter, how much does it matter? 如果订单确实重要,那有多重要? Of course, calling methods like .Equals probably results is a much larger slow-down than if I was just comparing a few integers, but is it a relatively small performance penalty compared to how 'slow' LINQ operates? 当然,像.Equals这样的调用方法可能会比我只是比较几个整数时的速度大得多,但是与LINQ运行的“慢”相比,这是一个相对较小的性能损失吗? As LINQ makes tons of method calls, is something like .Equals really going to matter since--unless its overridden--it'll be executing native framework code, right? 由于LINQ进行大量的方法调用,就像.Equals真的重要 - 因为 - 除非它被覆盖 - 它将执行本机框架代码,对吧? On the other hand, is a standard MSIL method call going to be significantly slower? 另一方面,标准的MSIL方法调用会明显变慢吗?

Also, are there any other compiler optimizations on this query which might be speeding this up under the hood? 此外,是否有任何其他编译器优化此查询可能会加快这一点?

Thanks for the thoughts and clarification! 感谢您的想法和澄清! Brett 布雷特

The answer is going to be different for different LINQ providers. 对于不同的LINQ提供商,答案将会有所不同。 In particular, the story is very different for LINQ to Objects and say LINQ to Entities. 特别是,LINQ to Objects和LINQ to Entities的故事非常不同。

In LINQ to Objects, the Where operator accepts the filter as Func<TSource, bool>. 在LINQ to Objects中,Where运算符接受过滤器为Func <TSource,bool>。 Func<,> is a delegate, so for the purposes of this discussion, you can think of it as a function pointer. Func <,>是委托,因此为了讨论的目的,您可以将其视为函数指针。 In LINQ to Objects, your query is equivalent to this: 在LINQ to Objects中,您的查询等效于:

static void Main() {
    List<TestItem> results = items.Where(MyFilter).ToList(); 

static boolean MyFilter(TestItem item) {
    return item.Item1 == 12 && 
        item.Item2 != null && 
        item.Item2.SubItem == 65 && 
        item.Item3.Equals(anotherThingy)
}

The main thing to notice is that MyFilter is an ordinary C# method and so ordinary C# rules apply, including the short-circuiting behavior of &&. 需要注意的主要问题是MyFilter是一种普通的C#方法,因此适用普通的C#规则,包括&&的短路行为。 Consequently, the conditions will be evaluated in the order you wrote them. 因此,将按您编写的顺序评估条件。 LINQ to Objects can invoke MyFilter on different input elements, but it cannot change what MyFilter does. LINQ to Objects可以在不同的输入元素上调用MyFilter,但它不能改变MyFilter的功能。

In LINQ to Entities and LINQ to SQL, the Where operator accepts the filter as Expression<Func<TSource, bool>> . 在LINQ to Entities和LINQ to SQL中,Where运算符接受过滤器作为Expression <Func <TSource,bool >> Now, the filter is passed into the Where operator as a data structure that describes the expression. 现在,过滤器作为描述表达式的数据结构传递给Where运算符。 In that case, the LINQ provider will look at the data structure (the "expression tree") and it is up to the LINQ provider to decide how to interpret it. 在这种情况下,LINQ提供程序将查看数据结构(“表达式树”),由LINQ提供程序决定如何解释它。

In LINQ to Entities and LINQ to SQL cases, the expression tree will be translated to SQL. 在LINQ to Entities和LINQ to SQL案例中,表达式树将被转换为SQL。 And then it is up to the database server to decide how to execute the query. 然后由数据库服务器决定如何执行查询。 The server is definitely allowed to reorder the conditions, and it may do even more substantial optimizations. 绝对允许服务器重新排序条件,它可以进行更实质的优化。 For example, if the SQL table contains an index on one of the columns referenced in the condition, the server can choose to use the index and avoid even looking at rows that don't match that particular condition part. 例如,如果SQL表包含条件中引用的其中一列的索引,则服务器可以选择使用索引,甚至避免查看与该特定条件部分不匹配的行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM