繁体   English   中英

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

[英]Is order of the predicate important when using 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方法调用会明显变慢吗?

此外,是否有任何其他编译器优化此查询可能会加快这一点?

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

对于不同的LINQ提供商,答案将会有所不同。 特别是,LINQ to Objects和LINQ to Entities的故事非常不同。

在LINQ to Objects中,Where运算符接受过滤器为Func <TSource,bool>。 Func <,>是委托,因此为了讨论的目的,您可以将其视为函数指针。 在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)
}

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

在LINQ to Entities和LINQ to SQL中,Where运算符接受过滤器作为Expression <Func <TSource,bool >> 现在,过滤器作为描述表达式的数据结构传递给Where运算符。 在这种情况下,LINQ提供程序将查看数据结构(“表达式树”),由LINQ提供程序决定如何解释它。

在LINQ to Entities和LINQ to SQL案例中,表达式树将被转换为SQL。 然后由数据库服务器决定如何执行查询。 绝对允许服务器重新排序条件,它可以进行更实质的优化。 例如,如果SQL表包含条件中引用的其中一列的索引,则服务器可以选择使用索引,甚至避免查看与该特定条件部分不匹配的行。

暂无
暂无

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

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