一次關閉綁定變量窺探_optim_peek_user_binds導致的存儲過程緩慢故障

一個客戶聯繫我,他寫了一個存儲過程,其中有一條insert into select的sql語句運行非常緩慢,平均處理每天的數據量需要4分鐘,而如果單獨執行此sql語句,其實很快,大概6s左右即可完成,返回的條數也不多,總共500條左右,希望幫忙優化一下.

1.先看一下正常的執行sql效率和執行計劃

此sql非常長,有多個union all連接而成,大概sql如下:

...

我們看到這個sql通過時間字段enter_date進行了限制,取一天的數據,而且時間字段上面有索引,所以直接執行的時候肯定是走索引的,下面是截取的某一段的執行計劃:

由於時間字段是非前綴,所以走的是index skip scan.

2.再看一下存儲過程中的執行計劃

執行存儲過程,在後臺通過sql_id查看此sql的真實執行計劃,這裏我們發現了問題:

這裏的inp_bill_detail是大表,上面有索引但是卻沒有走,而是進行了全表掃描,此過程中有多個類似的sql,全部都是大表的全表掃描,所以肯定就非常慢了

那麼我們這裏就找到了問題所在,相同的一段sql,直接執行和放到存儲過程中執行,卻有不同的執行計劃,過程中的執行計劃很差,導致的運行緩慢.

那麼這一段看似相同的sql爲啥執行計劃不一樣呢?sql有什麼不同嗎?

其實很容易就可以看到,在plsql中直接執行的時候,沒有使用綁定變量,是直接輸入的參數值,而在過程中執行的時候是使用的綁定變量.那麼我們這裏想到很可能是綁定變量的原因導致的.

oracle中綁定變量窺探,由隱藏參數_optim_peek_user_binds設置,默認爲true開啓,當開啓了綁定變量窺探,在使用綁定變量的時候,oracle內部會自動窺探綁定變量的值,從而選擇合適的執行計劃.

 一般在oltp環境基本都關閉此參數,防止因爲綁定變量的原因導致的執行計劃不穩定,檢查當前數據庫的設置爲false:

但是這裏明顯應該是要開啓綁定變量窺探,對查詢數據進行限制,執行計劃纔對.

 

3.解決辦法

既然此參數爲false而且數據庫運行正常,如果冒然修改此參數可能會帶來不確定因素,影響其它正常運行的sql,因此建議還是在sql級別進行單獨調整.

使用hint在sql級別進行調整:

調整後的sql執行計劃如下:

最後經過確認,每天處理的數據的時間由原來的4分鐘減少到了4秒,效果明顯!

 

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