我遇到了Sql Server 2008 R2的性能問題,我已經縮小到查詢優化器(我認爲!)。我正在尋找一個明確的「爲什麼發生這種情況,還是它是一個錯誤?」。查詢優化不使用索引
爲了討論的緣故,我將使用這個例子,但是在同一個場景中多個sprocs中也出現了相同的問題。 我們有一張包含付款方式的表格;關鍵字段是PaymentMethodId和UserId。 PaymentMethodId是一個int,而PK; UserId是一個具有非聚集索引的nvarchar(255)。
查詢類似於以下內容:
存儲過程PARAMS值得一提: @id INT = NULL @userId爲nvarchar(255)= NULL 有一個if語句在存儲過程的開始禁止兩個參數都是空的。
select * from PaymentMethods (nolock) pm
where (@userId is null or @userId = pm.UserId)
and (@id is null or @id = pm.PaymentMethodId)
在@userId爲空的情況下,我希望優化器檢測到第一個where子句始終爲true;如果@userId不爲空,我期望它使用UserId上的索引。 我對@id有同樣的期望。
我們看到的是,無論輸入值爲何,數據庫都會選擇執行全表掃描。雖然這涉及到其自身,但它變得更有趣。
將查詢where子句更新爲下面的等效項時,它正確使用indecies。
select * from PaymentMethods (nolock) pm
where ((@userId is null and pm.UserId is null) OR @userId = pm.UserId)
and (@id is null or @id = pm.PaymentMethodId)
這是怎麼回事?爲什麼每個記錄都會考慮「@userId爲null」,或者是真正的問題坐在他們的鍵盤前面?
可能是因爲(a)你的表很小(行數很少),或者(b)因爲你使用'SELECT *',索引無法「覆蓋」該查詢,所以很多密鑰查找將是必要的,並且最終這將比僅執行全表掃描更昂貴。 –
表中有1130萬條記錄,並且實際查詢通過名稱而不是*調用字段。 – Jon
請發佈查詢計劃的快照。你有表格定義和樣本數據嗎?幾條記錄。 –