Sql Server中存儲過程使用時間長了查詢效率變得很慢的分析

1. 問題描述:

同一各存儲過程,第一次創建並執行查詢只要幾十毫秒,使用一段時間後執行查詢竟然需要3秒多!!!

2. 分析問題

一般碰到這種問題,我的第一個想法是:數據量太大導致查詢時間提高。帶着這個設想我查看了一下數據庫的數據,發現數據量是有所提升但將查詢單獨拿出做sql查詢時,查詢時間還是幾十毫秒。而一旦執行存儲過程查詢,查詢時間又成了3秒。

因爲對數據庫優化器瞭解不多,所以沒想到執行計劃的問題。當時的想法是是否是查詢語句的原因,打開存儲過程發現之前因時間原因查詢語句結構寫得有點亂,就隨手把結構調一調方便自己查看並排查原因。看了一會還是沒找到問題怎麼辦?肯定要執行一下得吧,畢竟優化了結構也是可以得,雖然沒找到原因。注意,就是這個動作讓我意外發現問題得所在:當我點完執行,生成新的執行計劃後,我再調用這個存儲過程,奇蹟發生了。原本執行需要3秒得查詢又變回幾十毫秒,那麼問題應該就是出現再執行計劃上面了。

通過查找資料,我瞭解到存儲過程是預編譯的,存儲過程在上一次執行過程中就生成了最優的執行計劃並將之緩存起來,後面我們再繼續調用該存儲過程都是用的該緩存的執行計劃,而隨着數據的變化和數據量的增加,該緩存執行計劃對於後面傳入的參數來說並非是最優的執行計劃了,這也就是參數嗅探問題參數嗅探問題定位的流程可參考:講的很詳細的參數嗅探問題流程

3. 解決方式

既然緩存的存儲過程不是實際的最優執行計劃,那麼我們在調用存儲過程的時候進行一次強制重編譯就好了,重編譯後在拿到最新的執行計劃。強制重編譯的方法:在定義存儲過程後加WITH  RECOMPILE ,具體操作如下圖:

對於查詢不是很頻繁的存儲過程,可使用OPTION (OPTIMIZE FOR UNKNOWN)解決參數嗅探問題,那麼OPTION (OPTIMIZE FOR UNKNOWN)又是何物呢,官方的解釋是:

OPTIMIZE FOR 編譯和優化查詢時提示查詢優化器對本地變量使用特定值。僅在查詢優化期間使用該值,在查詢執行期間不使用該值。

指定查詢優化器在查詢優化期間使用統計數據而不是初始值來確定局部變量的值。OPTIMIZE FOR 可以抵消優化器的默認參數檢測行爲,也可在創建計劃指南時使用

OPTIMIZE FOR UNKNOWN

指示查詢優化器在查詢已經過編譯和優化時爲所有局部變量使用統計數據而不是初始值,包括使用強制參數化創建的參數。有關強制參數化的詳細信息,請參閱強制參數化

如果在同一查詢提示中使用 OPTIMIZE FOR @variable\_name = literal_constant 和 OPTIMIZE FOR UNKNOWN,則查詢優化器將對特定的值使用指定的 literal_constant,而對其餘變量使用 UNKNOWN。這些值僅用於查詢優化期間,而不會用於查詢執行期間

使用方法:

所以對於查詢頻繁的可以用強制生成新執行計劃,對於查詢不頻繁的用OPTION (OPTIMIZE FOR UNKNOWN)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章