在報表數據庫的後台alert文件中發現了這個錯誤,簡單記錄一下問題的診斷和解決過程。數據庫版本9204 for Solaris sparc64。
尋找產生問題的真正原因。
在第一篇文章中,定位了問題並且找到了解決方法;在第二篇文章中,找到了導致源數據庫和目標數據庫執行計劃不同的原因。
但是到目前為止,還沒有找到這個問題產生的真正原因。
首先理一下思路,根據第一篇文章的描述,產生ORA-4030問題的原因是由於一個大數據量的插入語句選擇了一個十分糟糕的執行計劃。而導致Oracle選擇了這個執行計劃的直接原因是由於列的統計信息出現了錯誤。而在第二篇文章中,可以確認由於源數據庫的版本為9201,沒有使用列統計信息中的DENSITY列,所以沒有引發這個問題。而在目標數據庫版本為9204,Oracle使用了統計信息列DENSITY的值,所以Oracle認為訪問ORD_HIT_COMM表且通過ENABLE_FLAG列進行限制,只會返回1條記錄,這就導致了Oracle產生了一個錯誤的離譜的執行計劃。
現在的問題是什麼導致了源數據庫錯誤統計信息的產生。
這就需要檢查源數據庫數據和統計的來源。因為在源數據庫9201上直接收集統計信息,是不會得到這種DENSITY的。
經過檢查發現這個9201的源數據庫仍然不是數據的真正源頭,而真正的來源數據庫版本是10203。
發現了這個信息,那麼問題的產生就不奇怪了。
看一下10203上這張表的統計信息:
SQL>SELECTCOLUMN_NAME,NUM_DISTINCT,NUM_NULLS,DENSITY,NUM_BUCKETS,HISTOGRAM
2FROMUSER_TAB_COLUMNS
3WHERETABLE_NAME='ORD_HIT_COMM'
4ANDCOLUMN_NAME='ENABLE_FLAG';
COLUMN_NAMENUM_DISTINCTNUM_NULLSDENSITYNUM_BUCKETSHISTOGRAM
----------------------------------------------------------------------
ENABLE_FLAG202.8355E-072FREQUENCY
可以看到,在Oracle10g使用了BUCKETS的設置,而且USER_TAB_COLUMNS添加了一個字段HISTOGRAM用來表示列的統計信息的類型。
FREQUENCY類型和以往的HEIGHT BALANCED類似的列統計不同。使用FREQUENCY類型,Oracle會選擇與NUM_DISTINCT相同數量的NUM_BUCKETS來進行直方圖統計,而直方圖統計信息方式和基於高度的統計信息是不同的。最關鍵的是,這種統計方式的DENSITY的結果和HEIGHT BALANCED的計算方式大不相同。
因此在10g中,由於Oracle了解當前列的統計信息方式為FREQUENCY類型,因此可以根據直方圖的信息得到正確的執行計劃和返回記錄數:
SQL>SELECTCOLUMN_NAME,NUM_DISTINCT,NUM_NULLS,DENSITY,NUM_BUCKETS,HISTOGRAM
2FROMUSER_TAB_COLUMNS
3WHERETABLE_NAME='ORD_HIT_COMM'
4ANDCOLUMN_NAME='ENABLE_FLAG';
COLUMN_NAMENUM_DISTINCTNUM_NULLSDENSITYNUM_BUCKETSHISTOGRAM
----------------------------------------------------------------------
ENABLE_FLAG202.8355E-072FREQUENCY
1rowselected.
SQL>EXPLAINPLANFOR
2SELECT*FROMORD_HIT_COMMWHEREENABLE_FLAG='1';
Explained.
SQL>SELECT*FROMTABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------
-----------------------------------------------------------------------
|Id|Operation|Name|Rows|Bytes|Cost(%CPU)|
-----------------------------------------------------------------------
|0|SELECTSTATEMENT||1691K|1200M|34103(2)|
|1|TABLEACCESSFULL|ORD_HIT_COMM|1691K|1200M|34103(2)|
-----------------------------------------------------------------------
11rowsselected.
但是如果將統計信息導入到920數據庫中,就會存在嚴重的問題。由於9i的數據庫中沒有表示統計信息類型的HISTOGRAM列,因此即使是基於FREQUENCY類型的統計信息,也會被當作基於HEIGHT BALANCED類型的統計信息。