假設我有這樣一個SQL語句在代碼的某處先前設置的變量@FOO如下:查詢優化TSQL否則
SELECT FIELDLIST
FROM TABLE
WHERE
(FIELD = @FOO OR @FOO IS NULL)
是查詢優化器足夠聰明,做OR的第二面第一個(@FOO IS NULL)是因爲(另一個假設)執行空檢查比執行字段比較更快?
我已經做了一些非正式的基準測試,不僅我看不出有什麼區別,而且在我的嘗試中得到了不同的結果時間,這導致了進行適當比較的能力。
假設我有這樣一個SQL語句在代碼的某處先前設置的變量@FOO如下:查詢優化TSQL否則
SELECT FIELDLIST
FROM TABLE
WHERE
(FIELD = @FOO OR @FOO IS NULL)
是查詢優化器足夠聰明,做OR的第二面第一個(@FOO IS NULL)是因爲(另一個假設)執行空檢查比執行字段比較更快?
我已經做了一些非正式的基準測試,不僅我看不出有什麼區別,而且在我的嘗試中得到了不同的結果時間,這導致了進行適當比較的能力。
簡短的答案...
是,優化器是足夠聰明。
較長的答案...
SQL是聲明,而不是命令式:您的查詢的條件的描述,你的結果必須符合,它是不一步一步如何產生的說明那些結果。
優化程序以最有效的順序執行查詢。它不保證以任何特定的順序評估你的子句,甚至根本不評估它 - 如果能夠在不評估特定子句的情況下得到正確的結果,那麼爲什麼它會受到影響?
任何特定查詢的實際評估順序都是一個實現細節,並且可以隨時間變化(例如,隨着表上的統計信息的變化)。
在實踐中,優化器偶爾會出錯,但在這種特殊情況下 - 將變量與NULL或從表或索引讀取進行比較 - 我認爲它沒有太大的可能性,儘管您可能會想要consider using OPTION(RECOMPILE)
or OPTION(OPTIMIZE FOR ...)
。
它足夠聰明,先應用更快的條件,假設它可以判斷在一般情況下哪種比較更快。在這種情況下,NULL檢查幾乎總是比較快,因爲它必須比較表達式的每一邊最多一個字節,並且可以將它分解出來。
試着用相反的順序條款測試它:
SELECT FIELDLIST
FROM TABLE
WHERE
(@FOO IS NULL OR FIELD = @FOO)
您可能會發現第一個測試短路第二,而不是相反。
是的,這是我的想法,但它可能取決於實現。 – 2009-02-12 18:18:07
如果此查詢位於存儲過程中,可能在此處起作用的一個因素是「參數嗅探」。這可能會導致查詢響應時間不一致。爲了解決這個問題,在你的sproc中聲明一個內部變量,並將這個變量賦值給參數值,然後在你的where子句中使用內部變量,或者在你的存儲過程中使用RECOMPILE子句。關於這個問題有很多鏈接。
根據我的經驗,有時使用兩個查詢和一個「UNION」而不是「OR」子句的速度會更快。
SELECT FIELDLIST
FROM TABLE
WHERE
(FIELD = @FOO)
UNION
SELECT FIELDLIST
FROM TABLE
WHERE
(@FOO IS NULL)
該方法的缺點是重複SELECT語句,但性能提高1500%是正確的。當然,這取決於數據庫結構(在我的情況下它很糟糕,我無法改變它)。
你確定你需要用你的時間來處理那些事嗎? 看看盧克關於SQL是什麼和不是什麼的答案... 並嘗試更廣泛地審視這個問題:如果這樣一個簡單的查詢對您來說是一個問題,那麼您可能稱它爲太多次... – siukurnin 2009-02-13 10:31:14
漂亮當然他只是用這個作爲一個理論的例子來證明他的觀點/問題,那就是你是否可以在SQL優化器中使用帶變量的查詢...... – 2013-10-02 18:41:49