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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM