前言
撰寫 SQL 不僅要正確,更要高效。以下彙總 34 條優化原則,涵蓋查詢順序、索引運用、函數替代、交易控制等核心技巧,助你寫出高效能的 SQL 陳述式。
查詢結構優化
- 表連接順序(Rule-based Optimizer):Oracle 從右往左解析 FROM 子句,將筆數最少的表放在最後(作為驅動表);超過 3 表連接時,選擇被多表引用的交叉表為驅動表。
- WHERE 子句條件順序:自下而上解析,表連接條件寫在前面,過濾力最強的條件寫在最後。
- 避免 SELECT *:解析器需查詢資料字典展開所有欄位,增加開銷。
- 減少資料庫存取次數:合併簡單無關聯查詢、使用陣列參數(如 SQL*Plus 設
ARRAYSIZE=200)。
- 善用 DECODE/CASE 函數:避免重複掃描同一表或重複連接。
- 整合無關聯的簡單查詢:多條單表查詢可合併為一條。
資料操作優化
- 刪除重複記錄最高效寫法(使用 ROWID):
DELETE FROM EMP E
WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X
WHERE X.EMP_NO = E.EMP_NO);
- 用 TRUNCATE 替代 DELETE(全表刪除):TRUNCATE 為 DDL,不產生 Rollback、不觸發 Trigger、速度極快、不可回復。
- 適時 COMMIT:釋放 Rollback Segment、鎖、Redo Log Buffer 等資源。
- 用 WHERE 替代 HAVING:WHERE 在聚合前過濾,減少排序/統計開銷;HAVING 在聚合後過濾。
- 減少子查詢中的表存取:如將
WHERE (col1,col2) IN (SELECT col1,col2 FROM ...) 優化為連接。
索引與執行計畫
- 善用內部函數提升效率:複雜 SQL 常犧牲效率,掌握函數改寫技巧至關重要。
- 使用表別名:多表連接時加上別名並冠於欄位前,減少解析時間與歧義。
- 用 EXISTS 替代 IN、NOT EXISTS 替代 NOT IN:NOT IN 會對子查詢全表掃描並排序合併,效率最低;改寫為 Outer Join 或 NOT EXISTS。
- 識別低效 SQL:自寫監控腳本,如查詢
V$SQLAREA 找出緩衝區命中率低、磁碟讀取高的語句。
- 索引策略:
- 索引加快查詢,但增加 INSERT/UPDATE/DELETE 開銷(每筆約 4-5 次額外 I/O)。
- 大表建索引效果明顯,小表全表掃描可能更快。
- 避免不必要的索引;定期
ALTER INDEX ... REBUILD 重建索引。
其他實用技巧
- 避免在索引欄位上使用函數或運算式,否則索引失效。
- 使用
UNION ALL 代替 UNION(無需去重時)。
- 大量插入時暫時停用索引/觸發器/約束,完成後重建。
- 分頁查詢優化:使用鍵值篩選而非 OFFSET/FETCH(視資料庫而定)。
- 統計資訊保持最新,讓優化器產生最佳執行計畫。
- 避免隱性型別轉換,導致索引無法使用。
- 適當使用資料分割、平行查詢、物化視圖等進階功能。
總結
SQL 優化無絕對真理,需結合具體資料庫版本、資料量、執行計畫實測調整。養成「先 EXPLAIN 再上線」的習慣,持續監控與迭代,才能寫出真正高效的 SQL。