2025年7月27日 星期日

Oracle Plan Baseline 固定之談



 
Oracle版本 : 19.3.0

觀察一個 DB 執行SQL 會忽快忽慢, 通常會 建立 SQL Plan Baseline , 目的是 防止 Optimizer 隨統計資訊波動而「選錯計畫」,用來 穩定高頻、高價值 SQL 的效能行為

可以看出來 oracle 的建議 



有出現兩個 plan hash , 一個是 0.047 秒, 另外一個是 3.923秒  
這樣我們就知道 建立 Plan Baseline 是 3426048666 是 0.047 秒這一個 plan hash 


BEGIN
  DBMS_SQLTUNE.CREATE_SQL_PLAN_BASELINE(
    task_name        => 'TASK_111258',     -- 實際 Tuning Task 名稱
    owner_name       => 'SYS',                   -- 建立該 Task 的使用者
    plan_hash_value  => 3426048666        -- 最快計畫的 hash 值
  );
END;
/



*-----------------------------*

但建立  Plan Baseline 也不是萬無一失
以下操作會讓  Plan Baseline 中的 hash value 無法命中 , 而讓SQL執行爆走


Oracle 的 hash value 不是純邏輯計劃,而是對執行路徑中一連串 operation、成本估算、物件資訊的 hash 結果, 以下這些都會改變 hash 值 

Index Rebuild : 可能會變, Oracle 會重新估算 I/O 路徑與成本
Gather Statistics : 高機率會變 , 當 num_rows, distinct_keys, clustering_factor 改變
改變 Optimizer 參數 : 可能會變, 如 _optimizer_cost_model、optimizer_mode



通常 有觀察到 index rebuild 後  SQL 反而不穩定, 可以再次執行  建立 Plan Baseline , 讓他固定

執行完後 可以查一下 是否有使用剛剛建立的 base line 

SELECT sql_id, sql_plan_baseline, executions
FROM v$sql
WHERE sql_id = '6z7p1645q3gzga';


SELECT *
FROM dba_sql_plan_baselines



*-----------------------------*

企業生產上用法可以這樣

-- 在 rebuild 前,先記錄好 baseline plan hash
SELECT sql_handle, plan_name, plan_hash_value
FROM dba_sql_plan_baselines
WHERE sql_text LIKE '%SQL內容%';

-- Rebuild 後重新 evolve 舊 baseline 
EXEC DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(sql_handle => '...', plan_name => '...');

-- 或從 Cursor Cache reload 新的好計畫


或者 重新在跑一次評估, 再次建立新的 baseline