首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

ORA-4030 診斷實戰(三):統計信息遷移導致的執行計劃災難

     編輯:Oracle 資料庫相關知識

一、問題回顧

  • 現象:大數據量 INSERT 選擇極差執行計劃,觸發 ORA-4030(進程內存不足);
  • 根因:列 ENABLE_FLAG 的統計信息中 DENSITY 錯誤,導致優化器誤估基數為 1 行;
  • 版本差異:源庫 9.2.0.1 未使用 DENSITY,目標庫 9.2.0.4 使用了該值,故僅目標庫發病。

二、深挖:錯誤統計信息從何而來?

排查發現:源庫 9.2.0.1 並非數據真正源頭,真實源頭為 10.2.0.3。

三、10g 統計信息新特性:FREQUENCY 直方圖

SELECT COLUMN_NAME, NUM_DISTINCT, NUM_NULLS, DENSITY, NUM_BUCKETS, HISTOGRAM
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME='ORD_HIT_COMM' AND COLUMN_NAME='ENABLE_FLAG';

結果:

ENABLE_FLAG  2  0  2.8355E-07  2  FREQUENCY
  • HISTOGRAM = FREQUENCY:10g 引入的頻率直方圖,NUM_BUCKETS = NUM_DISTINCT;
  • DENSITY 計算方式與舊版 HEIGHT BALANCED 截然不同,極小值(2.8E-7)反映極高選擇性。

四、跨版本統計遷移的災難性後果

  1. 10g 優化器識別 HISTOGRAM 類型,結合直方圖桶信息正確估算基數(169 萬行);
  2. 統計信息導入 9i 後,9i 數據字典缺少 HISTOGRAM 列,無法識別直方圖類型;
  3. 9i 優化器將其視為傳統 HEIGHT BALANCED 直方圖,直接使用 DENSITY 估算,導致基數錯估為 1 行;
  4. 優化器選擇 NESTED LOOPS + 索引掃描,實際返回百萬行,PGA 爆滿 → ORA-4030。

五、驗證對比

-- 10g 正確計劃
EXPLAIN PLAN FOR SELECT * FROM ORD_HIT_COMM WHERE ENABLE_FLAG='1';
-- 顯示全表掃描,基數 1691K

-- 9i 導入統計後錯誤計劃
-- 顯示索引範圍掃描,基數 1

六、解決方案與最佳實踐

  1. 重新採集統計信息:在目標庫直接執行 DBMS_STATS.GATHER_TABLE_STATS,生成匹配版本的統計信息;
  2. 跨版本遷移時:切勿直接導入統計信息,必須在目標版本重新採集;
  3. 升級前評估:關注 HISTOGRAM、DENSITY、NUM_BUCKETS 等新列的兼容性;
  4. 鎖定統計信息:核心表可用 DBMS_STATS.LOCK_TABLE_STATS 防止自動採集產生波動。

總結

統計信息不可跨主版本直接遷移。10g 引入的頻率直方圖與 9i 的元數據結構不兼容,導致優化器誤讀 DENSITY,引發連鎖性能災難。重新採集是唯一正確出路。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved