DB2 可擴展性仰賴「小而優化的 SQL + 精準的存取路徑 + 適配負載的緩衝池與儲存」。硬體升級只能暫緩瓶頸,SQL 層面的架構優化才是根本。當資料量與併發上升,原本在輕量負載下運作良好的「巢狀游標、大量子查詢、SELECT *」將成為災難。
批次程式在 7 個巢狀游標中逐層讀取 7 張表,並在應用層以程式邏輯做連接。首次上線跑 10 個小時仍未完成。
SELECT COL1, COL2, ...
FROM ADDR A, NAME N, T3, T4, T5, T6, T7
WHERE A.COL1 = N.COL9
AND N.COL9 = T3.COL3
AND T3.COL3 = T4.COL4
AND T4.COL4 <> T5.COL5
AND T4.COLX <> T5.COLY
AND T5.COL6 = T6.COL6
AND T6.COL6 = T7.COL7
AND T6.CODE = :hv
執行時間從 10+ 小時降至 4 分鐘。
優化器以兩張龐大表(ADDR、NAME,各 5 億列)為外層驅動,導致嵌套循環連接極度膨脹。原因在於 <> 不等值連接條件,統計資訊無法準確估算選擇率。
| 層次 | 技術 | 適用場景 | 本案例效果 |
|---|---|---|---|
| Package 級 | REOPT(ONCE/ALWAYS/AUTO) |
非均勻分布、主機變數高變動 | 批次僅單一謂詞 + 基數 1,開銷可忽略,但非最佳解 |
| Statement 級 | OPTIMIZE FOR n ROWS / FETCH FIRST n ROWS ONLY |
僅需前 N 筆結果 | 批次需全量結果,不適用 |
| Predicate 級 | 假過濾器 TX.CX=TX.CX / 空操作 +0, *1, CONCAT '' |
調整過濾因子、改變連接順序 | 多重嘗試無效,LUW 優化器忽略空操作 |
| 終極重寫 | SELECT DISTINCT 表表達式 / 跨查詢塊優化 |
強制指定查詢塊執行順序 | 生效,再降至 2 分鐘 |
將小表優先連接、過濾後再與大表連接:
SELECT All columns needed
FROM ADDR, NAME,
(SELECT DISTINCT columns
FROM T3, T4, T5, T6, T7
WHERE join conditions T3 through T7
AND T6.CODE = :hv) AS TEMP
WHERE join conditions for ADDR, NAME and TEMP
DISTINCT 關鍵:強制優化器先實例化子查詢結果(唯一化並排序),再與外層大表連接。DISTINCT,優化器會合併查詢塊,退回原始連接順序。DB2 9 起引入 Global Query Optimization,優化器在 Query Rewrite (QWR) 階段自動嘗試跨查詢塊重寫。未來版本將更完善,但現階段仍需開發者掌握手動重寫技法,確保關鍵路徑受控。
RUNSTATS 含分佈統計,確保優化器擁有精準全景。DISTINCT 表表達式可能由好變壞,上線前必須完整回歸測試。掌握從結構重構到優化器導引的完整技法組合,即能在不升級硬體前提下,榨乾 DB2 SQL 引擎的效能潛力。