數據庫突發性能問題,有時可能經過重啓應用、從新收集統計信息、重啓數據庫等方法獲得臨時解決,可是,如何把故障根本緣由找到,避免故障再次發生,是問題獲得完美閉環的一個關鍵步驟(固然,可以快速恢復業務也是很是關鍵的一環)。這也是爲何不少對業務穩定性要求很是高的行業(好比金融、通訊、鐵路、航空等)的數據庫系統,購買oracle 售後高服(ACS)中的頂級服務SSC服務的一個主要緣由。算法
根因分析的另一個重要性就是找到問題的責任方:運維、開發仍是數據庫產品自身緣由(缺陷或是bug),有的問題是單方問題,有的可能幾個方面都有。根因分析的結論會影響到部門考覈,一個你們都信服的結論,可讓背鍋的一方心服口服。有時候讓產品背鍋,也是一個比較好的結局。sql
見過網上有人分享一些故障處理的文章,雖然問題獲得瞭解決,可是根因分析的結論倒是徹底錯誤的,好比有一個結論是index unique scan效率遠遠大於index range scan的案例,把一個數據庫直方圖侷限性的問題,「有理有據」的解釋成了索引掃描方式的問題,實屬低級錯誤,誤導觀衆。
數據庫
今天介紹的這個案例是一個學員發來的,請我對一個銀行業務系統的SQL執行計劃突變致使的性能問題作根因分析。我花了半小時左右對這個問題進行了分析,並給出了根因。性能優化
問題描述:微信
2019-11-21 零時左右, 某重要業務SQL執行計劃發生改變,執行效率嚴重降低。下面是採集到的sqlhc信息(數據庫版本 11.2.0.4):oracle
根據上圖信息能夠看到,執行計劃的cost變小了,效率卻降低了幾千倍。運維
對於有經驗的優化專家來講,對於這個問題的第一反應就是謂詞越界,按照這個思路,很快拿到證據(客戶認爲信息敏感,這裏就不貼過多的細節),並給出根因。性能
根因分析:
優化
一、經過表的統計信息收集歷史能夠查到,11月20日晚,數據庫對錶作了自動統計信息收集。知識點1:工做日天天的22:00~02:00這個時段,系統會對須要從新收集統計信息的表,收集統計信息。
spa
二、知識點2:統計信息收集後的一段時間內,會對使用該表的相關SQL作硬解析。
三、知識點3:硬解析時,會發生綁定變量窺視。若是窺視到的綁定變量,超出了字段上統計信息的最大最小(通常是最大)值範圍,就可能發生謂詞越界。謂詞越界就可能會出現索引選擇錯誤,致使生成低效執行計劃。
四、知識點4:真正的謂詞越界通常發生在varchar2和number字段,日期字段雖然常常發生越界,可是系統對於日期類型字段的越界算法,有必定的容忍度,不會認爲是真正的越界。這個sql發生越界的字段保存的數據是日期數據,可是使用的倒是number類型。這裏面涉及到一個重要的開發規範相關內容:很是不建議用number或varchar2類型保存日期數據,規範作法是使用date類型。上面數據類型隨意使用的作法是開發人員爲了少敲幾個字母的偷懶行爲。由於按天查詢時,date類型通常須要寫兩段範圍條件,而number或varchar2類型,能夠用一個等值條件便可完成,並且不用作to_date轉換。這種偷懶的不規範作法,會給SQL性能帶來較大的性能隱患。
五、知識點5:發生謂詞越界後,數據庫優化器在評估這個sql可使用的兩個索引(都是以越界字段開頭的組合索引)時,就不是常規的選擇方式,而是選擇leaf blocks較少的那一個,這個案例,leaf blocks較少的那個索引,剛好是低效的那一個。
下圖上面是正常執行計劃使用的高效索引,sql用到了索引的所有3個字段;下面是性能故障時執行計劃使用的低效索引,sql只用到了JYRQ(number類型保存日期數據)一個字段:
下圖#1對應的是上面的高效索引,#2對應上面的低效索引:
六、知識點6:sqlhc捕獲到了sql後面的一些執行狀況,不少使用的綁定變量已經再也不越界,並且系統的自適應遊標(ACS)保持開啓狀態,爲何ACS沒能及時把執行計劃調整回正常? 這裏面又涉及到另外一個不規範的狀況:綁定變量使用的數據類型是char,剛剛咱們提到字段使用的類型是number,優化器須要對綁定變量作to_number隱式類型轉換,這種轉換致使了ACS不生效。
七、知識點7:網上不少文章介紹說要關閉ACS,本人對這個說法不太贊同,這個案例,雖然ACS由於綁定變量類型不匹配沒有生效,可是若是綁定變量使用的數據類型也是number,那麼ACS就會生效,不會出現執行計劃一錯到底的狀況:對於後面謂詞不越界的狀況,ACS還能及時調整回正常的執行計劃。ACS在11g版本引入,開始時bug較多,到了11204版本,不少bug已經修復了,它起到的做用遠遠高於bug帶來的一些小問題。
總結:
經過以上分析,明顯這個問題的根本緣由是開發人員使用不合適的數據類型保存日期數據,致使謂詞越界很是容易發生;同時又使用了錯誤的綁定變量數據類型,讓優化器的ACS功能失效。這個鍋,徹底應該由開發人員來背。 可是,若是運維人員沒有掌握上面的知識點,就沒法分析出根因,那這個性能故障的鍋就只能本身揹着。
這個sql,若是開發不作代碼調整,相同故障仍有可能再次出現。臨時解決方法是先使用sql profile綁定執行計劃。
更多案例與原理,本人在線下培訓時會詳細解讀,12.28~12.29,2019年度最後一站,深圳見。
(完)
本文分享自微信公衆號 - 老虎劉談oracle性能優化(sql_tigerliu)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。