Cardinality Feedback特性導致執行計劃不穩定
前段時間,在專案中碰到一個相當棘手的問題。我在寫一張報表時需要查詢客戶資料庫中已存在的檢視(是早期開發就有的),相對應的銷售表中已有上千萬條資料,寫完後臺邏輯將對應資料查出來沒任何問題。但是在介面上再點選查詢按鈕。問題就來了:頁面直接卡死。
排除掉其他常見問題,例如語句效能,索引,快取等等。最後發現奇怪的現象,正常來講同樣的一條SQL查詢語句,根據執行計劃,第一次查詢完以後,後續再執行相同的語句應該很快才對。可是,現實卻是第一次查詢不慢(優化後2秒內查詢),第二次以後就掛掉。困擾了好久不知道問題所在,也向相關群裡的大牛去諮詢也得不到結果。(資料庫為oracle11G,專案為.net EF開發模式。)
最後求助團隊老大,老大找來專業的DBA終於找出原因。
其實,算是Oracle11G的一個BUG。。。
11.2開始Oracle有了一種新的特性Cardinality Feedback,Cardinality Feedback是一個優化器自動優化的過程,優化器會自動修正重複執行的查詢的執行計劃。對於一些複雜的查詢,比如多欄位條件,字串範圍比較,資料SKEW等等,以及缺乏統計資訊,優化器可能不能夠產生一個完全準確的基數估計, 如丟失或統計資料不準確,或複雜的謂詞的基數估計。cardinality feedback 就是基於這一原因而產生的。_optimizer_use_feedback引數預設是TRUE,即開啟Cardinality Feedback,FALSE為關閉Cardinality feedback。由於在11GR2中Cardinality feedback生效存在很多限制且BUG較多,故沒必要啟用。
上段話是同事知道了原因後整理出來了的。 也就是說要關閉oracle的一個引數,對於結構上不復雜的語句,其實是看不到什麼影響的。
alter system set "_optimizer_use_feedback"=false;
可以以一下方式驗證引數是否真正關閉。
SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describe FROM SYS.x$ksppi x, SYS.x$ksppcv y WHERE x.inst_id = USERENV('Instance') AND y.inst_id = USERENV('Instance') AND x.indx = y.indx AND x.ksppinm LIKE '%optimizer_use_feedback%';
結果:引數關閉後,同樣的語句,多次執行,已經不再會掛掉,跟資料庫上千萬的資料沒有多大關係,每次執行可以保證在兩秒左右。至此問題總算能解決。