某銀行核心系統,穩定運行多年。某批次作業原本 30 分鐘完成,突然暴增至 3+ 小時仍未結束。排除資料量暴增後,鎖定問題核心:執行計畫變更,根因為統計資訊過舊導致優化器誤判。
-- 查詢長時間運行 Session SELECT sid, serial#, sql_id, username, status, last_call_et FROM v$session WHERE status = 'ACTIVE' AND last_call_et > 1800 -- 超過 30 分鐘 AND username IS NOT NULL;
-- 透過 AWR 歷史檢視 SQL 執行趨勢
SELECT b.begin_interval_time,
a.plan_hash_value,
a.executions_total,
a.elapsed_time_total/1e6 elapsed_sec,
a.cpu_time_total/1e6 cpu_sec,
a.buffer_gets_total,
a.disk_reads_total,
a.rows_processed_total
FROM dba_hist_sqlstat a
JOIN dba_hist_snapshot b ON a.snap_id = b.snap_id
WHERE a.sql_id = '&sql_id'
ORDER BY b.begin_interval_time DESC;
-- 檢查相關表統計資訊時間
SELECT table_name, last_analyzed, num_rows, blocks, sample_size
FROM dba_tables
WHERE owner = '&owner' AND table_name IN ('TARGET_TABLE_1', 'TARGET_TABLE_2');
-- 檢查索引統計資訊
SELECT index_name, last_analyzed, distinct_keys, clustering_factor
FROM dba_indexes
WHERE table_owner = '&owner' AND table_name = 'TARGET_TABLE';
EXEC DBMS_STATS.GATHER_TABLE_STATS( ownname => 'SCOTT', -- Schema 名稱 tabname => 'TARGET_TABLE', -- 表名稱 estimate_percent => 10, -- 抽樣百分比(100 為全表,預設 DBMS_STATS.AUTO_SAMPLE_SIZE) method_opt => 'FOR ALL COLUMNS SIZE AUTO', -- 直方圖自動收集 degree => 8, -- 平行度 granularity => 'GLOBAL', -- 全域/分區統計 cascade => TRUE, -- 同步收集索引統計 no_invalidate => FALSE -- TRUE=不立即失效游標,FALSE=立即重解析 );
| 參數 | 大表建議 | 小表建議 | 說明 |
|---|---|---|---|
| estimate_percent | AUTO_SAMPLE_SIZE (11g+) | 100 (全表) | 11g+ 自動抽樣精準且快 |
| method_opt | FOR ALL COLUMNS SIZE AUTO | FOR ALL COLUMNS SIZE AUTO | 讓 Oracle 決定哪些欄位需直方圖 |
| degree | CPU 核心數 * 0.5~1 | 1 (串行) | 平行收集加速,避免佔滿資源 |
| granularity | GLOBAL AND PARTITION | GLOBAL | 分區表需同時收集分區與全域統計 |
| no_invalidate | FALSE (立即生效) | FALSE | 效能緊急時立即失效舊計畫 |
-- 1. 從游標快取載入基線
DECLARE
v_cnt PLS_INTEGER;
BEGIN
v_cnt := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(
sql_id => '&sql_id',
plan_hash_value => &plan_hash_value,
fixed => 'YES' -- 固定不變更
);
DBMS_OUTPUT.PUT_LINE('Loaded ' || v_cnt || ' plans');
END;
-- 2. 查詢基線狀態
SELECT sql_handle, plan_name, enabled, accepted, fixed, reproduced
FROM dba_sql_plan_baselines
WHERE sql_text LIKE '%TARGET_TABLE%';
統計資訊是 CBO 優化器的「眼睛」。過舊統計資訊導致計畫劣化是資料庫效能退化的首要原因。建立「自動收集+手動補充+關鍵表監控+SPM 固定」四層防護體系,是維持穩定效能的關鍵。