面對這條看似簡單的統計查詢,原始寫法在大數據量下效能低下。本文演示如何通過「子查詢去相關化、索引覆蓋、執行計畫分析」三步走策略,實現數量級效能提升。
SELECT SUM(sl0000)
FROM xstfxps2
WHERE dhao00 IN (
SELECT dhao00
FROM xstfxps1
WHERE TRUNC(ywrq00) = TRUNC(SYSDATE)
AND khdm00 = '500000003913'
);
問題剖析:
TRUNC(ywrq00) 使 ywrq00 上的索引無法使用,引發全表掃描。IN 子查詢優化較弱,易退化為 Filter 操作,逐行驗證外層表。sl0000,增加 I/O。WHERE ywrq00 >= TRUNC(SYSDATE)
AND ywrq00 < TRUNC(SYSDATE) + 1
利用日期範圍查詢替代 TRUNC,使 ywrq00 索引生效。
-- 寫法 A:標準內連接(推薦,優化器可選擇最佳連接順序)
SELECT SUM(t2.sl0000)
FROM xstfxps1 t1
JOIN xstfxps2 t2 ON t1.dhao00 = t2.dhao00
WHERE t1.ywrq00 >= TRUNC(SYSDATE)
AND t1.ywrq00 < TRUNC(SYSDATE) + 1
AND t1.khdm00 = '500000003913';
-- 寫法 B:EXISTS 相關子查詢(語義更精確:僅判斷存在性)
SELECT SUM(t2.sl0000)
FROM xstfxps2 t2
WHERE EXISTS (
SELECT 1 FROM xstfxps1 t1
WHERE t1.dhao00 = t2.dhao00
AND t1.ywrq00 >= TRUNC(SYSDATE)
AND t1.ywrq00 < TRUNC(SYSDATE) + 1
AND t1.khdm00 = '500000003913'
);
-- xstfxps1:過濾條件 + 連接鍵 + 選單欄位(此處無額外選單)
CREATE INDEX idx_xstfxps1_khdm_ywrq_dhao ON xstfxps1 (khdm00, ywrq00, dhao00);
-- xstfxps2:連接鍵 + 聚合欄位
CREATE INDEX idx_xstfxps2_dhao_sl ON xstfxps2 (dhao00, sl0000);
查詢僅掃描索引塊,**完全避免回表**,I/O 減少 90%+。
| 階段 | 操作類型 | 成本 | 關鍵指標 |
|---|---|---|---|
| 原始 | FULL TABLE SCAN xstfxps1 → FILTER → FULL TABLE SCAN xstfxps2 | 高 (如 12,450) | 全表掃描、函數失效、無索引 |
| 優化後 | INDEX RANGE SCAN idx_xstfxps1... → NESTED LOOPS → INDEX RANGE SCAN idx_xstfxps2... | 極低 (如 45) | 索引覆蓋、嵌套循環、零回表 |
Cost、Rows、Operation 三大指標。