我最近一直在重構一些舊查詢,并注意到其中很多在子句中重復ISNULL(),在GROUP BY子句中使用它SELECT。我從骨子里覺得洗掉ISNULL()inGROUP BY子句會提高性能,但我找不到任何關于它是否真的有可能的檔案。這就是我的意思:
SELECT
ISNULL(Foo,-1) AS Foo
,ISNULL(Bar,-1) AS Bar
,SUM(This) AS This
,SUM(That) AS That
FROM
dbo.ThisThatTable AS ThisThat
LEFT JOIN dbo.FooBarTable AS FooBar ON ThisThat.FooBarId = FooBar.Id
GROUP BY
ISNULL(Foo,-1)
,ISNULL(Bar,-1);
GO
以上是我不斷遇到的方式 - 當 Foo 列上有分組時,所選列的 theSELECT和GROUP BYfor 完全匹配。下面的示例是一個可能的替代方案 - 一些可能不必要ISNULL()的呼叫已被洗掉,SELECTandGROUP BY子句不再匹配。
SELECT
ISNULL(Foo,-1) AS Foo
,ISNULL(Bar,-1) AS Bar
,SUM(This) AS This
,SUM(That) AS That
FROM
dbo.ThisThatTable AS ThisThat
LEFT JOIN dbo.FooBarTable AS FooBar ON ThisThat.FooBarId = FooBar.Id
GROUP BY
Foo
,Bar;
GO
我想也許當 SELECT 和GROUP BY子句匹配時,優化器只需執行ISNULL()一次計算即可知道發生了什么,所以理論上按實際選擇的結果分組可能更具執行性?或者,也許最好避免添加第二組ISNULL()根本不改變資料粒度的呼叫......也許優化器足夠聰明,可以意識到分組中的 NULLS 是(在這種情況下) -選擇中的1s...?
我個人更喜歡洗掉任何不必要的功能,尤其是一旦可能影響索引使用的功能,但是當我在網上查看時,對性能的參考都像這里的答案,關于ISNULL()在子WHERE??句中使用,我已經知道要避免。
我也懷疑任何收益都會變得微乎其微,所以這確實是在尋求學術或理論答案,但是當我作業時,我一直在想,這讓我很煩惱,所以我想我會問是否有人有任何想法。
uj5u.com熱心網友回復:
SELECT 子句中的非聚合列通常必須與 GROUP BY 子句中的列精確匹配。如果我是你,并且我正在處理經過測驗的生產代碼,我不會做出你提議的改變。
GROUP BY 需要編輯非聚合 SELECT 列和 GROUP BY 列之間的匹配。如果 SELECT 中的列是 1:1 依賴于 GROUP BY 中的列,它將起作用。否則結果是模棱兩可的。
uj5u.com熱心網友回復:
在內部,SQL 實際上并沒有每個 ISNULL 的兩個副本。在編譯期間使用的內部樹中,它們都被展平在一起。因此,在 SQL Server 中考慮這種優化級別是沒有用的。沒有任何 ISNULL 的查詢可能會執行得更快一些,并且可能會更快,具體取決于架構和查詢的其余部分。然而,選擇串列中的 ISNULL 和 GROUP BY 串列在大多數情況下不會在 SQL 中執行兩次——這種詳細程度可以顯示在 showplan 中,但通常低于大多數人愿意檢查的詳細程度。
uj5u.com熱心網友回復:
這里有幾個不同的方面需要考慮:
在同一范圍內多次參考相同的值
在大多數情況下,優化器足夠聰明,可以將它們折疊成一次計算。你GROUP BY對他們有信心的事實使這種情況更有可能發生。當值保證不為空時,分組是否更快?
可能,盡管我懷疑差異是可衡量的。SELECT不必完全匹配,它只需要在功能上依賴于GROUP BY列和聚合函式。它可能在功能上不依賴于任何其他列。最重要的事情要考慮:索引。
這比其他考慮要重要得多。分組時,如果你可以點擊一個索引,那么它會更快,因為它可以洗掉排序并只使用Stream Aggregate.ISNULL如果您在GROUP BY(禁止計算列或索引視圖)中使用,這是不可能的。
請注意,您的結果將不同:第一個示例將組折疊NULL到-1組中。第二個例子沒有,所以你可能想ISNULL從SELECTalso中洗掉,以便區分它們。或者,換上一個WHERE ... IS NOT NULL。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/479179.html
