首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> DB2 資料庫 >> DB2 教學

SQL 性能調優核心原則與 DB2 實戰優化指南:從寫法到執行計劃的系統性提升

     編輯:DB2 教學

調優鐵律:測量 → 診斷 → 單一變更 → 驗證 → 固化

「過早優化是萬惡之源」 — 唐納德·克努斯。無基線不調優,無執行計劃不改寫,無統計信息不分析。

DB2 優化器架構與決策鏈


SQL 語句
    │
    ▼
解析器 (Parser) → 語義檢查器 (Semantic Checker) 
    │
    ▼
查詢重寫器 (Query Rewrite) 
    ├── 視圖合併、子查詢轉連接、常量折疊、謂詞下推
    ├── 物化視圖 (MQT) 匹配路由
    └── 星型連接轉換、分區剪枝
    │
    ▼
成本基礎優化器 (Cost-Based Optimizer - CBO)
    ├── 統計信息 (RUNSTATS) → 基數估算
    ├── 索引匹配 → 訪問路徑選擇 (IXSCAN/TBSCAN/IXAND)
    ├── 連接方法選擇 (NLJOIN/MSJOIN/HSJOIN)
    ├── 並行度決定 (INTRA_PARALLEL)
    └── 成本模型計算 (CPU/IO/COMM/MEMORY)
    │
    ▼
執行計劃生成 (Access Plan) → 計劃緩存 (Package Cache)
    │
    ▼
執行引擎 (Runtime Engine) → 結果集返回

寫法層面優化:讓優化器「看懂」你的意圖

1. 謂詞構造:索引友好 vs 索引殺手

❌ 索引殺手模式✅ 索引友好模式原理
WHERE UPPER(name) = 'SMITH'WHERE name = 'SMITH' (數據標準化) 或 CREATE INDEX idx_upper_name ON t(UPPER(name))函數列導致無法使用列索引 (SARGable 原則)
WHERE YEAR(date_col) = 2023WHERE date_col BETWEEN '2023-01-01' AND '2023-12-31'範圍謂詞可用索引區間掃描
WHERE col + 10 > 100WHERE col > 90列參與運算失去索引性
WHERE col IS NULL避免或建立 INCLUDE NULL KEYS 索引DB2 默認索引不包含 NULL (V9.7+ 可選包含)
WHERE col LIKE '%abc%'WHERE col LIKE 'abc%' 或全文索引前導通配符導致全表掃描
WHERE col IN (SELECT ... 關聯子查詢)WHERE EXISTS (SELECT 1 ...) 或 JOINEXISTS 半連接優化優於 IN 子查詢
WHERE NVL(col, 0) = 0WHERE col = 0 OR col IS NULL函數包裹破壞 SARGable

2. 連接寫法優化


-- ❌ 隱式連接 (舊語法,難維護、易錯)
SELECT * FROM a, b WHERE a.id = b.id AND a.type = 'X';

-- ✅ 顯式 ANSI JOIN (清晰語義、優化器更友好)
SELECT * FROM a INNER JOIN b ON a.id = b.id WHERE a.type = 'X';

-- 連接順序提示 (DB2 不支持 HINT,但可通過優化器配置影響)
-- 1. 確保連接列有索引
-- 2. 統計信息準確 (RUNSTATS WITH DISTRIBUTION)
-- 3. 小表驅動大表: 將過濾性強的表放在 FROM 最前 (優化器通常會自動重排)

3. 子查詢重寫策略

子查詢類型重寫目標示例
標量子查詢 (SELECT 列表中)JOIN + 聚合 或 物化視圖SELECT c.name, (SELECT AVG(sal) FROM emp WHERE dept=c.dept) FROM dept c → SELECT c.name, e.avg_sal FROM dept c LEFT JOIN (SELECT dept, AVG(sal) avg_sal FROM emp GROUP BY dept) e ON c.dept=e.dept
相關子查詢 (WHERE 中)EXISTS / NOT EXISTS / JOINWHERE NOT IN (SELECT ...) → WHERE NOT EXISTS (SELECT 1 ...) (NULL 安全)
派生表 (FROM 子查詢)CTE (WITH) 或 物化視圖WITH dept_stats AS (...) SELECT * FROM dept_stats JOIN ... 可複用、可物化

4. 排序與分頁優化


-- ❌ 全表排序後取前 N (大表災難)
SELECT * FROM huge_table ORDER BY created_at DESC FETCH FIRST 10 ROWS ONLY;

-- ✅ 索引支持的 Top-N
-- 前提: 存在 INDEX ON huge_table(created_at DESC)
-- 優化器自動使用索引順序掃描 + 早期停止

-- 深分頁優化 (OFFSET 100000 LIMIT 10)
-- 方案 A: 游標分頁 (記住上一頁最大 ID)
SELECT * FROM huge_table WHERE id > :last_max_id ORDER BY id FETCH FIRST 10 ROWS ONLY;

-- 方案 B: 覆蓋索引 + 子查詢
SELECT * FROM huge_table 
WHERE id IN (SELECT id FROM huge_table ORDER BY created_at DESC OFFSET 100000 LIMIT 10)
-- 內層只掃描索引鍵,外層回表 10 行

索引設計黃金法則

1. 索引列順序:等值 → 範圍 → 排序 → 覆蓋


-- 查詢: WHERE a=1 AND b>2 AND c=3 ORDER BY d
-- 最佳索引: (a, c, b, d)  -- a/c 等值優先,b 範圍,d 排序
-- 覆蓋索引: (a, c, b, d) INCLUDE (e, f) -- 包含 SELECT 列,避免回表

2. 索引類型選擇

類型適用場景DB2 語法
B-Tree (標準)OLTP 精確/範圍查詢、排序、分組CREATE INDEX ...
壓縮索引大量重複前綴列 (如 URL、路徑)CREATE INDEX ... COMPRESS YES
MDC (多維聚簇)數據倉庫多維範圍查詢CREATE TABLE ... ORGANIZE BY DIMENSIONS (dim1, dim2)
ITC (索引表聚簇)熱點表按業務鍵聚簇存儲CREATE INDEX ... CLUSTER
XML 索引XML 列路徑查詢CREATE INDEX ... GENERATE KEYS USING XMLPATTERN ...
文本索引 (Net Search Extender)全文檢索CALL SYSPROC.SYSTS_CREATE(...)
向量索引 (V11.5.7+)相似度搜索/RAGCREATE INDEX ... EXTENSION VECTOR(HNSW, DISTANCE=COSINE)

3. 索引維護策略

  • RUNSTATS 節奏:OLTP 每日增量 (RUNSTATS ON TABLE ... WITH DISTRIBUTION ON KEY COLUMNS),數倉每周全量
  • REORG 觸發:REORGCHK 指標 F1/F2/F3 > 100 或 REORG_RECOMMENDATION = '*'
  • 在線 REORG:REORG TABLE ... ALLOW WRITE ACCESS (V9.7+),業務零停機
  • 廢棄索引清理:db2pd -db x -indexes 找出 INDEXSCANS=0 且存在 > 30 天的索引

執行計劃深度解讀

獲取計劃三大法


-- 1. EXPLAIN 模式 (靜態/動態)
db2 "EXPLAIN PLAN FOR SELECT * FROM t WHERE id=1"
db2exfmt -d dbname -1 -o plan.txt -g TIC  # 格式化輸出

-- 2. db2pd 動態計劃緩存 (運行中 SQL)
db2pd -db dbname -dynamic -apinfo -file /tmp/dyn.sql

-- 3. 活動監控 (V9.7+)
CREATE EVENT MONITOR mon_act FOR ACTIVITIES WRITE TO TABLE;
SET EVENT MONITOR mon_act STATE 1;
-- 運行目標 SQL
SELECT * FROM ACTIVITYSTMT_MON_ACT WHERE STMT_TEXT LIKE '...';
-- 解析 XML 計劃

關鍵算子識別與優化對策

算子含義典型原因優化方向
TBSCAN表掃描無索引、統計失效、謂詞非 SARGable、小表創建索引、重寫謂詞、RUNSTATS、小表可忽略
IXSCAN索引掃描正常,但檢查是否為全索引掃描 (無 START/STOP KEY)優化謂詞順序、添加 INCLUDE 列覆蓋
SORT排序ORDER BY/GROUP BY/DISTINCT/UNION/連接輸入排序索引順序消除排序、增加 SORTHEAP、避免大排序
HSJOIN雜湊連接大表連接、無索引、非等值連接確保連接列有索引、考慮 NLJOIN/MSJOIN、調整 SORTHEAP
NLJOIN嵌套循環連接小表驅動大表、外表有索引通常最優,檢查內表索引是否命中
MSJOIN合併連接兩輸入已排序、等值連接優於 HSJOIN,確保輸入有序 (索引/排序)
TEMP臨時表物化複雜子查詢、派生表、排序溢寫重寫為 CTE/JOIN、增加 SORTHEAP/TEMP 空間
FILTER後置過濾索引無法完全應用謂詞優化索引列順序、添加 INCLUDE 列

統計信息:優化器的「眼睛」


-- 基礎收集 (快速)
RUNSTATS ON TABLE schema.table WITH DISTRIBUTION ON KEY COLUMNS AND DETAILED INDEXES ALL;

-- 全量收集 (準確,耗時長)
RUNSTATS ON TABLE schema.table WITH DISTRIBUTION ON ALL COLUMNS AND DETAILED INDEXES ALL ALLOW WRITE ACCESS;

-- 系統級自動收集 (STMM 配合)
UPDATE DB CFG USING AUTO_RUNSTATS ON AUTO_STMT_STATS ON AUTO_STATS_VIEWS ON;

-- 統計信息導出/導入 (跨環境復現)
CALL SYSPROC.EXPORT_STATS('DBNAME', '/tmp/stats', 'C');
CALL SYSPROC.IMPORT_STATS('DBNAME', '/tmp/stats', 'C');

配置參數對性能的杠桿作用

調優實戰檢查清單 (按 ROI 排序)

  1. 統計信息:RUNSTATS 全量 + 分佈 — 成本最低、收益最高
  2. 索引缺失:db2advis / EXPLAIN 找 TBSCAN/SORT → 創建索引
  3. 謂詞重寫:消除函數列、前導通配符、隱式轉換 — 零成本、即時生效
  4. 內存參數:SORTHEAP/LOCKLIST/PCKCACHESZ — 動態生效、立竿見影
  5. 並行度:INTRA_PARALLEL + DFT_DEGREE=ANY — 大查詢加速明顯
  6. 分區/MDC:大表範圍查詢 — 架構級優化、需規劃
  7. MQT/物化視圖:重複聚合查詢 — 預計算換空間換時間
  8. 應用邏輯:批量操作、減少往返、連接池 — 代碼層面、收益最大

總結

SQL 性能調優是 統計信息準確性、索引設計合理性、寫法 SARGable 化、配置參數適配性 四大支柱的系統工程。DB2 提供了完整的工具鏈 (RUNSTATS/db2advis/EXPLAIN/db2pd/db2top/活動監控) 支持科學調優。核心心法:

信數據、信計劃、信工具、信迭代。
每次只改一處,驗證效果,固化最佳實踐。
調優無終點,只有在當前業務負載下的「足夠好」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
參數調優方向典型值範圍影響維度
SORTHEAP調大防止排序溢寫1000-10000 (4KB 頁)排序、雜湊連接、索引創建
SHEAPTHRES_SHR共享排序閾值 = SORTHEAP * 並發排序估算SORTHEAP * 10-50並發排序內存保護
LOCKLIST調大防止鎖升級10000-100000 (4KB)並發、死鎖、鎖等待
MAXLOCKS配合 LOCKLIST 調高80-95單應用鎖佔用上限
PCKCACHESZ調大減少編譯開銷AUTOMATIC 或 20000+動態 SQL 編譯緩存命中率
DFT_DEGREE啟用查詢並行ANY (配合 INTRA_PARALLEL=ON)大查詢並行度
NUM_IOSERVERS匹配磁盤陣列數物理磁盤數 / CPU 核心數預取並行度
CHNGPGS_THRESH異步寫入觸發閾值40-60 (默認 60)髒頁刷新平滑度