我需要使用相同的查詢兩次,但有一個稍微不同的where子句。我在想,如果簡單地用一個值來調用相同的存儲過程是有效的,並且有一個IF ... ELSE ...語句,可以決定要比較哪些字段。Sql Server如何爲存儲過程中的邏輯流編譯執行計劃?
或者我應該做兩個存儲的特效,並調用基於邏輯在我的應用程序每一個?
雖然爲了正確理解,但我想詳細瞭解這一點。 如何爲此編譯執行計劃?每個IF ... ELSE ...中的每個代碼塊是否有一個?
還是編譯成一個大的執行計劃?
我需要使用相同的查詢兩次,但有一個稍微不同的where子句。我在想,如果簡單地用一個值來調用相同的存儲過程是有效的,並且有一個IF ... ELSE ...語句,可以決定要比較哪些字段。Sql Server如何爲存儲過程中的邏輯流編譯執行計劃?
或者我應該做兩個存儲的特效,並調用基於邏輯在我的應用程序每一個?
雖然爲了正確理解,但我想詳細瞭解這一點。 如何爲此編譯執行計劃?每個IF ... ELSE ...中的每個代碼塊是否有一個?
還是編譯成一個大的執行計劃?
它使用傳遞到過程的參數的初始值編譯一次。雖然有些語句可能會受到延遲編譯的影響,但在這種情況下,它們將在最終編譯時隨參數值進行編譯。
您可以從運行的下方,並着眼於實際的執行計劃看到這一點。
CREATE TABLE T
(
C INT
)
INSERT INTO T
SELECT 1 AS C
UNION ALL
SELECT TOP (1000) 2
FROM master..spt_values
UNION ALL
SELECT TOP (1000) 3
FROM master..spt_values
GO
CREATE PROC P @C INT
AS
IF @C = 1
BEGIN
SELECT '1'
FROM T
WHERE C = @C
END
ELSE IF @C = 2
BEGIN
SELECT '2'
FROM T
WHERE C = @C
END
ELSE IF @C = 3
BEGIN
CREATE TABLE #T
(
X INT
)
INSERT INTO #T
VALUES (1)
SELECT '3'
FROM T,
#T
WHERE C = @C
END
GO
EXEC P 1
EXEC P 2
EXEC P 3
DROP PROC P
DROP TABLE T
運行2
情況下示出了從作爲T
不1
未來1000
行的估計數,因爲該聲明是根據在1
傳遞的初始參數值編譯。運行3
案例給出的準確估計數爲1000
,因爲對臨時表(即將創建)的引用意味着該語句受到延遲編譯的影響。
您有權關注正在緩存的執行計劃。
馬丁給出了一個很好的例子顯示,該計劃被緩存,併爲您的邏輯是第一次執行的某個分支將得到優化。 第一次執行完該計劃後,即使您使用不同的參數調用存儲過程(sproc),導致您的執行流程選擇另一個分支,該計劃也會被重用。 這非常糟糕,會導致性能下降。我已經多次看到這種情況,需要一段時間才能找到根本原因。
這個背後的原因被稱爲「參數嗅探」,它是非常值得研究。
一個共同提出的解決方案(一說,我不諮詢)是你的存儲過程分成幾個微小的。 如果你在一個sproc內部調用一個sproc,那麼內部sproc會得到一個針對傳遞給它的參數進行優化的執行計劃。
分裂一個存儲過程成幾個小的時候沒有很好的理由(一個很好的理由將是模塊化)是一個醜陋的解決方法。 Martin表示可以通過引入對模式的更改來重新編譯語句。 我會在聲明結尾使用OPTION(RECOMPILE)。這指示優化器在考慮當前值全部變量的情況下進行語句重新編譯:不僅參數而且局部變量也被考慮在內,這可以導致好的和壞的計劃之間的差異。
回來你構建一個查詢與不同的地方根據參數條款的問題。我會用以下模式:
WHERE
(@parameter1 is null or col1 = @parameter1 )
AND
(@parameter2 is null or col2 = @parameter2 )
...
OPTION (RECOMPILE)
的一面是,該語句的執行計劃不會被緩存(不影響雖然緩存到語句的點),它可以有如果衝擊由於現在應該考慮編譯時間,因此多次執行sproc。使用生產質量數據進行測試會給你答案,如果這是一個問題或不。
好處在於,您可以編寫可讀且優雅的sprocs,而不是將優化器設置在錯誤的腳上。
另一個需要記住的選擇是,您可以禁用執行計劃緩存在精度較低的精靈級別(而不是語句級別)級別,更重要的是,不會考慮局部變量的值優化時。在 http://www.sommarskog.se/dyn-search-2005.html http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/
爲什麼沒有upvotes?一個合法的答案。 –
會是什麼'IF ... ELSE
更多信息.. .'(或'CASE')恰好包含?在某些情況下,將條件抽象爲參數可能更有效。每個proc都有一個執行計劃,因此條件邏輯可能會導致性能不均衡。 –