2012-02-24 62 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