2

我有一個SP sp在一個表中執行,其索引在三列col_1,col_2,col_3,col_4,col_n中執行。 Col 1是一個身份。 col_2,col_3,col_4上有一個索引。當查詢條件值爲空時,查詢計劃顯示99%的密鑰查找

當我查詢類似

@parameter=1 

SELECT col_2,col_3,col_4 
WHERE [email protected] 
AND col_3='2' 
AND col_4=10.00 

它使用之前我提到的,但如果我查詢類似

@paramete =null; -- the parameter is null in this case when parameter 
has value it uses the index 

SELECT col_2,col_3,col_4 
WHERE (@parameter is null OR col_2 = @parameter) 
AND col_3='2' 
AND col_4=10.00 

它顯示了一個關鍵的查詢計劃的索引查找上COL_1用99%的成本。

有時候這個值是空的,我必須保持那樣。

有人可以解釋這一點嗎?它可以修復嗎?

謝謝。

+2

這正是這種類型的查詢將始終工作。它通常被稱爲「全部捕獲」查詢。這裏有一篇很好的文章,討論這種類型的查詢以及如何解決這個問題。 https://www.simple-talk.com/sql/t-sql-programming/how-to-confuse-the-sql-server-query-optimizer/ –

回答

0

首先,加OPTION(RECOMPILE)到查詢:

SELECT col_2,col_3,col_4 
WHERE 
    (@parameter is null OR col_2 = @parameter) 
    AND col_3='2' 
    AND col_4=10.00 
OPTION(RECOMPILE); 

詳情請參見優秀的文章Dynamic Search Conditions in T‑SQL通過厄蘭Sommarskog。


如果@parameter不爲NULL,與OPTION(RECOMPILE)查詢實際上就變成這樣:

SELECT col_2,col_3,col_4 
WHERE 
    col_2 = <actual_parameter_value> 
    AND col_3='2' 
    AND col_4=10.00 

col_2,col_3,col_4索引可以用來快速查找此查詢所需的列。


如果@parameter爲NULL,與OPTION(RECOMPILE)查詢實際上就變成這樣:

SELECT col_2,col_3,col_4 
WHERE 
    col_3='2' 
    AND col_4=10.00 

現在很明顯,在col_2,col_3,col_4指數是沒有幫助這裏。您需要col_3,col_4 include (col_2)上的第二個索引來提高效率。


另一方面,具有不同列順序的單個索引將有助於兩種情況。所以,而不是索引col_2,col_3,col_4創建和索引col_4,col_3,col_2col_3,col_4,col_2。在索引定義中放置col_2最後一個。它將在兩種情況下都有效使用(使用OPTION(RECOMPILE))。