使用LINQ时谓词的顺序重要吗? [英] Is order of the predicate important when using LINQ?

查看:79
本文介绍了使用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();

这是更快的一个:

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

但这不是我的问题:

But that is not my question:

我的问题是与LINQ谓词有关的短路性能.当我使用Where子句时,例如这种情况:

My question is about performance of the short circuiting as it relates to a LINQ predicate. When I use a Where clause, like in this case:

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

参数的顺序不重要吗?例如,我希望首先执行.Equals会导致总体查询速度变慢,这是因为Item1 == 12整数求值是一种更快的操作?

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这样的调用方法所导致的减速比与我只比较几个整数相比要慢得多,但是与慢速" LINQ的运行方式相比,它的性能损失相对较小吗?由于LINQ进行了大量的方法调用,所以类似的问题就变得很重要,因为-除非被覆盖-它将执行本机框架代码,对不对?另一方面,标准的MSIL方法调用会明显变慢吗?

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? 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? On the other hand, is a standard MSIL method call going to be significantly slower?

此外,此查询是否还有其他编译器优化可能会在后台进行优化?

Also, are there any other compiler optimizations on this query which might be speeding this up under the hood?

感谢您的想法和澄清! 布雷特(Brett)

Thanks for the thoughts and clarification! Brett

推荐答案

对于不同的LINQ提供程序,答案将有所不同.尤其是,对于LINQ to Objects和LINQ to Entities来说,故事截然不同.

The answer is going to be different for different LINQ providers. In particular, the story is very different for LINQ to Objects and say LINQ to Entities.

在LINQ to Objects中,Where运算符将过滤器作为Func< TSource,bool>接受. Func< ;,>是一个委托,因此出于讨论目的,您可以将其视为函数指针.在LINQ to Objects中,您的查询与此等效:

In LINQ to Objects, the Where operator accepts the filter as Func<TSource, bool>. Func<,> is a delegate, so for the purposes of this discussion, you can think of it as a function pointer. In LINQ to Objects, your query is equivalent to this:

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)
}

主要要注意的是MyFilter是普通的C#方法,因此适用普通的C#规则,包括&&&的短路行为.因此,条件将按照您编写条件的顺序进行评估. LINQ to Objects可以在不同的输入元素上调用MyFilter,但不能更改MyFilter的功能.

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 &&. 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 Entities和LINQ to SQL中,Where运算符将过滤器接受为 Expression< Func< TSource,bool>> .现在,过滤器作为描述表达式的数据结构传递到Where运算符中.在这种情况下,LINQ提供程序将查看数据结构(表达式树"),这取决于LINQ提供程序来决定如何解释它.

In LINQ to Entities and LINQ to SQL, the Where operator accepts the filter as Expression<Func<TSource, bool>>. Now, the filter is passed into the Where operator as a data structure that describes the expression. 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 to Entities和LINQ to SQL情况下,表达式树将转换为SQL.然后由数据库服务器决定如何执行查询.绝对允许服务器对条件进行重新排序,并且它甚至可以进行更大量的优化.例如,如果SQL表在条件中引用的列之一上包含索引,则服务器可以选择使用索引,甚至避免查看与该特定条件部分不匹配的行.

In LINQ to Entities and LINQ to SQL cases, the expression tree will be translated to 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.

这篇关于使用LINQ时谓词的顺序重要吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆