統計顯示:硬體、OS、網路、參數調校總共僅貢獻 40% 效能提升,剩餘 60%~80% 來自應用程式與 SQL 優化。本文聚焦 WHERE 子句常見陷阱,示範錯誤寫法導致索引失效、全表掃描的案例。
含 NULL 的欄位不進入 B-Tree 索引。任何 WHERE col IS NULL 或 IS NOT NULL 皆無法使用該欄索引。
對策:給預設值(如 DEFAULT 'N'),或使用函式式索引 CREATE INDEX idx_nvl ON t(NVL(col, 'X'))。
-- 錯誤:無法使用 last_name 索引
SELECT * FROM employee WHERE first_name || ' ' || last_name = 'George Bush';
-- 正確:可使用 last_name 索引
SELECT * FROM employee WHERE first_name = 'George' AND last_name = 'Bush';
-- 變數拆解法(函式不可用於索引欄)
SELECT * FROM employee
WHERE first_name = SUBSTR(:name, 1, INSTR(:name, ' ')-1)
AND last_name = SUBSTR(:name, INSTR(:name, ' ')+1);
-- 無法使用索引
SELECT * FROM employee WHERE last_name LIKE '%Bush%';
-- 可使用索引
SELECT * FROM employee WHERE last_name LIKE 'Bush%';
若業務必須模糊前綴,可考慮 Oracle Text、反向鍵索引 + REVERSE() 或 函式式索引。
「能用索引就用索引,能少掃描就少掃描。」每一條 SQL 寫完,先 EXPLAIN PLAN 確認存取路徑,再上線。