本系列第九篇,聚焦三項高頻優化技巧。
多表聯結時,為每個表指定別名並冠於所有欄位前。效益:
-- 不佳 SELECT empno, ename, dname FROM emp, dept WHERE emp.deptno = dept.deptno; -- 推薦 SELECT e.empno, e.ename, d.dname FROM emp e, dept d WHERE e.deptno = d.deptno;
子查詢作為篩選條件時,EXISTS 通常比 IN 高效。
-- 低效 (IN)
SELECT * FROM emp
WHERE empno > 0
AND deptno IN (SELECT deptno FROM dept WHERE loc = 'MELB');
-- 高效 (EXISTS)
SELECT * FROM emp e
WHERE e.empno > 0
AND EXISTS (SELECT 'X' FROM dept d
WHERE d.deptno = e.deptno AND d.loc = 'MELB');
原理:EXISTS 只需檢查是否存在滿足條件的列,一旦找到即停止;IN 需物化子查詢結果集並排序/合併。
NOT IN 是最低效寫法:對子查詢表全表掃描 + 排序合併。
-- 低效 (NOT IN)
SELECT ... FROM emp
WHERE dept_no NOT IN (SELECT dept_no FROM dept WHERE dept_cat = 'A');
-- 方法一:外連接 (高效)
SELECT ... FROM emp a, dept b
WHERE a.dept_no = b.dept_no(+)
AND b.dept_no IS NULL
AND b.dept_cat(+) = 'A';
-- 方法二:NOT EXISTS (最高效)
SELECT ... FROM emp e
WHERE NOT EXISTS (SELECT 'X' FROM dept d
WHERE d.dept_no = e.dept_no
AND d.dept_cat = 'A');
注意:NOT IN 遇到子查詢含 NULL 會回傳零列 (邏輯陷阱);NOT EXISTS 無此問題。
養成「優先用 EXISTS/NOT EXISTS、必加表別名」習慣,能消除大多數子查詢效能隱患。