DB2 效能調優是系統生命週期中的持續課題。本文提煉六大高頻實戰策略,涵蓋索引、分區、日誌、鎖、臨時表與連接寫法,助你精準定位瓶頸、實現量級提升。
核心原則:「先建索引再寫入」與「寫入後建索引 + RUNSTATS」各有優劣,視業務容忍度選擇。
NOT LOGGED INITIALLY),但統計資訊過期導致優化器忽略索引;必須緊接 RUNSTATS ON TABLE schema.table AND INDEXES ALL 更新統計,才能讓優化器生成最佳執行計畫。建議:大批量載入(ETL、初始化)採「後建索引 + RUNSTATS」;日常增量業務採「先建索引」。
架構痛點:單節點表空間(如 DIM 維度表空間)僅能利用該節點 CPU/記憶體(例:2 CPU + 4GB),並發查詢時資源爭搶嚴重。
解決方案:
ALTER TABLE ... ACTIVATE NOT LOGGED INITIALLY WITH EMPTY TABLE 或 LOAD ... NONRECOVERABLE。
DROP RECREATE 重來;嚴禁用於核心業務線上表,適用於可重跑的暫存表、階段表、數據倉庫載入窗口。DB2 鎖上限受 LOCKLIST、MAXLOCKS 制約,海量行鎖會擠佔記憶體並觸發鎖升級(Lock Escalation)導致並發度驟降。
ALTER TABLE schema.table LOCKSIZE TABLE 強制使用表鎖,犧牲細粒度並發換取穩定的鎖記憶體佔用。常見反模式:為加速報表,將全量明細塞入臨時表,實際查詢僅用 10% 欄位/行。
INSERT INTO temp SELECT col1, col2, col3 FROM ... 而非 SELECT *。CREATE INDEX idx_temp_key ON temp(key_col),後續連接/聚合可走索引掃描而非全表掃描。錯誤寫法:
SELECT *
FROM fact f
LEFT JOIN dim d ON f.dim_key = d.dim_key
AND d.status = 'A' -- 對右表過濾寫在 ON 中 ✅
AND f.date = '2024-01-01'; -- 對主表過濾錯誤寫在 ON 中 ❌
正確寫法:
SELECT *
FROM fact f
LEFT JOIN dim d ON f.dim_key = d.dim_key
AND d.status = 'A' -- 右表限制留在 ON
WHERE f.date = '2024-01-01'; -- 主表限制放在 WHERE
原理:主表過濾條件寫在 ON 中會導致優化器無法下推謂詞,產生龐大中間結果集;寫在 WHERE 可在掃描主表前就完成過濾,並保持 LEFT JOIN 語義不變。
| 策略 | 關鍵動作 | 避坑提醒 |
|---|---|---|
| 索引時機 | 大量載入:後建 + RUNSTATS | 忘記 RUNSTATS 導致全表掃描 |
| 多節點部署 | 分區鍵 + 多節點表空間 + 索引 | 只並行不建索引 |
| NOT LOGGED | 可重跑暫存表專用 | 核心表誤用導致資料不可恢復 |
| 表級鎖 | 批次/唯讀窗口 | OLTP 核心表禁用 |
| 臨時表 | 窄欄位 + 少行數 + 索引 | SELECT * 進臨時表 |
| LEFT JOIN | 主表條件 WHERE,右表條件 ON | 主表條件寫在 ON 導致效能崩塌 |
將這六大策略內化為開發規範與審核清單,能讓 DB2 系統在高併發、大數據量場景下持續保持優異效能。