SQL 語句效能優化是資料庫開發核心技能。本文提煉五大經典優化原則:WHERE 條件排序、表別名使用、EXISTS 替代 DISTINCT、WHERE 替代 HAVING、善用系統函數,並說明各原則的底層邏輯與適用場景。
Oracle 解析 WHERE 子句採自下而上順序 (舊版 RBO 特徵,CBO 會自動最佳化,但良好習慣仍有助穩定)。建議:
-- 推薦:連接條件在前,過濾條件在後 SELECT e.empno, e.ename, d.dname FROM emp e, dept d WHERE e.deptno = d.deptno -- 連接條件優先 AND e.deptno = 20; -- 強過濾條件在後 -- 不推薦:過濾條件在前 SELECT e.empno, e.ename, d.dname FROM emp e, dept d WHERE e.deptno = 20 AND e.deptno = d.deptno;
SELECT e.empno, e.ename, e.job, e.sal, e.deptno, d.dname FROM emp e, dept d WHERE e.deptno = d.deptno AND e.deptno = 20;
一對多連接產生重複行時,DISTINCT 需排序去重,消耗大;EXISTS 子查詢遇到第一筆匹配即返回,無需掃描全部。
-- 推薦:EXISTS 半連接 SELECT d.deptno, d.dname FROM dept d WHERE EXISTS (SELECT 'Y' FROM emp e WHERE e.deptno = d.deptno); -- 不推薦:DISTINCT 全掃描去重 SELECT DISTINCT d.deptno, d.dname FROM dept d, emp e WHERE e.deptno = d.deptno;
SQL 執行順序:WHERE → GROUP BY → HAVING → ORDER BY。非聚合過濾條件應在 WHERE 階段過濾,減少進入分組的行數。
-- 推薦:WHERE 早期過濾 SELECT deptno, AVG(sal) FROM emp WHERE deptno IN (10, 20) GROUP BY deptno; -- 不推薦:HAVING 晚期過濾 SELECT deptno, AVG(sal) FROM emp GROUP BY deptno HAVING deptno IN (10, 20);
例外: 涉及聚合函數的過濾 (如 HAVING AVG(sal) > 2000) 必須用 HAVING。
Oracle 內建函數經過高度優化,處理資料型別轉換、字串操作、日期運算等比自寫 PL/SQL 或複雜 SQL 表達式更可靠、高效。
這五大原則是寫出高效 SQL 的基礎習慣。進階優化需結合:執行計劃分析、索引設計、統計資訊收集、分區表、物化視圖、結果快取等技術。但無論多進階,基礎寫法規範永遠是第一步。