2017-09-27 39 views
0

我正在開發大量的存儲過程,並且其中大多數存在與以下類似的where子句。存儲過程其中包含許多參數的語句

WHERE 
    (CE.EnquiryDate >= @StartDate or @StartDate is null) and 
    (CE.EnquiryDate <= @EndDate or @EndDate is null) and 
    (CE.ClientID = @ClientID or @ClientID is null) 

我關心的是性能,只有當一個clientId傳遞則顯然會被潛在的產生導致問題走下賽場,也就是說,如果一個計劃是在SP上的第一次執行緩存執行計劃與不傳遞ClientID並且StartDate和EndDate是不同的。

我在這裏最好把這些分成多個存儲過程或使用OPTION (RECOMPILE)在每次運行中得到一個新的計劃?只是想知道最好的方法是在發展的早期階段。

+0

您可以使用'選項(重新編譯)動態SQL'以確保每次運行一個最優的執行計劃。 –

+0

感謝Gordon,但是在將它添加到sp的底部而不是具有執行動態SQL的效果方面沒有相同的效果? – Philip

+0

。 。值得一試。也許SQL Server更聰明地用''或'''子參數來優化where子句。 –

回答

2

這個問題的標準治療方法是Erland Sommarskog的Dynamic Search Conditions in T-SQL。請仔細閱讀,瞭解有關技術和權衡的完整討論。

由於SQL 2008 SQL Server將在使用OPTION RECOMPILE時優化此類查詢的查詢計劃。在編譯期間,對應於空參數的謂詞將從查詢中刪除。所以OPTION RECOMPILE是我在這裏的默認值,但是如果你有一些搜索模式,你需要超級便宜,你可以在使用OPTION RECOMPILE之前全面使用它們。

喜歡的東西:

IF (@StartDate is not null and @ClientId is not null) 
BEGIN 

    SELECT * 
    FROM T 
    WHERE 
     (CE.EnquiryDate >= @StartDate) and 
     (CE.EnquiryDate <= @EndDate or @EndDate is null) and 
     (CE.ClientID = @ClientID) 

    RETURN 
END 


SELECT * 
FROM T 
WHERE 
    (CE.EnquiryDate >= @StartDate or @StartDate is null) and 
    (CE.EnquiryDate <= @EndDate or @EndDate is null) and 
    (CE.ClientID = @ClientID or @ClientID is null) 
WITH (OPTION RECOMPILE) 
+0

感謝您的答覆大衛,感謝它。你能提供一個關於「特殊情況」的例子嗎?根據我在最初的問題中列出的內容?乾杯。 – Philip

+0

@詹姆斯他做了。這是第一個if語句的目的 - 這是一個「特例」。 – SMor

+0

我在@ James的評論中添加了一個例子。 –

0

試試這個:

WHERE 
    (CE.EnquiryDate >= ISNULL(@StartDate,CE.EnquiryDate)) and 
    (CE.EnquiryDate <= ISNULL(@EndDate,CE.EnquiryDate)) and 
    (CE.ClientID = ISNULL(@ClientID,CE.ClientID)) 

這可能是由於使用了 「< =」, 「> =」 和 「=」:不是「<工作「或」>「。

目標是要避免OR操作符......女巫太慢了。見執行計劃。

https://en.wikipedia.org/wiki/Boolean_algebra進一步的細節如何避免或者......

X OR Y = NOT (NOT X AND NOT Y) 
+0

不好。這兩個查詢都需要表掃描,並且ISNULL _also_要求爲每行評估ISNULL(@ param,col)表達式。這裏的問題更多的是關於是否對所有標準組合使用相同的計劃,或者找到一種方法來針對不同的搜索標準組合使用不同的計劃。 –

+0

不壞?很高興聽到來自微軟的^^RECOMPILE在這種情況下很聰明,但它傾向於系統地使用。 – clementakis

相關問題