2012-02-24 50 views
8

据我所知,在不同的顺序执行操作将产生不同的性能,如下面的慢速查询之间的区别:这一个更快的使用LINQ时谓词的顺序是否重要?

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(); 

但是,这不是我的问题:

我的问题是关于短路的表现,因为它关系重大测试一个LINQ谓词。当我使用Where子句时,就像在这种情况下一样:

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

参数的顺序不重要吗?例如,我期望首先执行一个.Equals会导致整个查询更慢,因为Item1 == 12整数评估是一个更快的操作?

如果订单确实重要,它有多重要?当然,调用像.Equals这样的方法可能会导致比仅仅比较几个整数更慢的性能下降,但是与LINQ运行速度相比,它的性能损失相对较小吗?由于LINQ进行大量的方法调用,就像.Equals真的很重要 - 除非被覆盖 - 它会执行本地框架代码,对吗?另一方面,标准的MSIL方法调用是否会显着变慢?

另外,是否有任何其他编译器优化在这个查询可能会加快这一点在引擎盖下?

感谢您的想法和澄清! Brett

+2

LINQ到什么地步? – SLaks 2012-02-24 19:09:41

+0

我在想LINQ to Objects,但是我想这个问题对于LINQ to SQL更重要。 – Brett 2012-02-24 19:11:02

+2

虽然我不知道LINQ____,但如果它与其他短语语言一样,顺序很重要,因为如果要评估的表达式变成绝对正确或绝对错误,其余谓词可以安全地丢弃。例如,在表达式'(1 == 1 || x == 3)'中,'x == 3'永远不会被评估,因为不管结果如何,表达式都是真实的。一个类似的简单例子可能是'(1 == 0 && x == 3)',在'1 == 0'后面发现它是错误的,它只是退出,因为表达式不可能是真的。对不起,如果这不是你要找的! – prelic 2012-02-24 19:13:27

回答

13

对于不同的LINQ提供者,答案会不同。特别是,对于LINQ to Objects和LINQ to Entities来说,这个故事非常不同。

在LINQ to Objects中,Where运算符接受过滤器为Func < TSource,bool >。函数<,>是一个委托,所以出于本次讨论的目的,您可以将其视为函数指针。在LINQ to对象,查询是相同的:

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的功能。

在LINQ到实体和LINQ to SQL时,如果操作者接受过滤器表达< Func键< TSource,布尔> >。现在,过滤器作为描述表达式的数据结构传递给Where运算符。在这种情况下,LINQ提供者将查看数据结构(“表达式树”),由LINQ提供者决定如何解释它。

在LINQ to Entities和LINQ to SQL的情况下,表达式树将被转换为SQL。然后由数据库服务器决定如何执行查询。服务器绝对可以对条件进行重新排序,并且可以做更多实质性的优化。例如,如果SQL表包含条件中引用的某个列的索引,则服务器可以选择使用索引,并避免查看不匹配该特定条件部分的行。

+0

感谢您的详细解答! – Brett 2012-02-27 23:56:48