基於規則優化器(RBO)與成本優化器(CBO)雙視角,匯總 34 條 Oracle SQL 調優鐵律,涵蓋表連接順序、WHERE 子句排序、索引失效模式、子查詢重寫、排序消除、分頁優化等核心場景,附帶 V$SQLAREA 慢 SQL 發現腳本與索引維護最佳實踐。
ARRAYSIZE=200。| 反模式 | 優化寫法 | 原理 |
|---|---|---|
DELETE ... WHERE rowid > (SELECT MIN(rowid) ...) | 同 | 利用 ROWID 直接定位重複行,避免全表掃描 |
DELETE FROM big_table | TRUNCATE TABLE big_table | DDL 不產生 UNDO,瞬間完成,不可回滾 |
HAVING col > 100 | WHERE col > 100 | WHERE 在聚合前過濾,避免排序/聚合開銷 |
IN (subquery) | EXISTS (correlated subquery) | EXISTS 可半連接,IN 可能物化子查詢 |
NOT IN (subquery) | NOT EXISTS / LEFT JOIN ... IS NULL | NOT IN 全表掃描子查詢,極慢 |
DISTINCT 多表連接 | EXISTS | EXISTS 命中即停止,避免排序去重 |
OR 連接索引列 | UNION ALL 分開查詢合併 | OR 導致全表掃描,UNION ALL 可用索引 |
col > 3 | col >= 4 | 直接定位首滿足行,避免掃描邊界值 |
col * 12 > 25000 | col > 25000/12 | 索引列參與運算導致失效,移項保持純列 |
IS NULL / IS NOT NULL 索引列 | col >= 0 (非負業務) | 空值不進 B-Tree 索引,改寫走索引 |
WHERE 引用首列才生效。ALTER INDEX idx REBUILD TABLESPACE ts; 消除碎片。UNION ALL 替代 UNION 省去排序去重,業務允許重複時首選。ORDER BY 僅在列全在同一索引且順序一致、且非空時用索引排序。WHERE char_col = 123 → TO_NUMBER(char_col)=123 失效,改 WHERE char_col = '123'。SELECT executions, disk_reads, buffer_gets,
ROUND((buffer_gets-disk_reads)/buffer_gets,2) hit_ratio,
ROUND(disk_reads/executions,2) reads_per_run,
sql_text
FROM v$sqlarea
WHERE executions > 0
AND buffer_gets > 0
AND (buffer_gets-disk_reads)/buffer_gets < 0.8
ORDER BY 4 DESC;
WHERE 過濾再 GROUP BY,減少分組輸入行數。ONLY_FULL_GROUP_BY 報錯。MIN/MAX 優化:SELECT MIN(id) FROM t → SELECT id FROM t ORDER BY id LIMIT 1 走索引。-- 延遲關聯法:先取主鑰再回表 SELECT a.* FROM big_table a JOIN (SELECT id FROM big_table WHERE cond ORDER BY id LIMIT 10000,20) b USING (id); -- 已知邊界值改範圍掃描 SELECT * FROM t WHERE id > 10000 ORDER BY id LIMIT 20;
IN (SELECT ...) → EXISTS / JOINSELECT 列表或改 OUTER APPLY(12c+)WITH 子句(Subquery Factoring)複用中間結果