經測試,COUNT(*) 經優化器優化後略快於 COUNT(1);若有索引欄位,COUNT(索引欄) 最快。
| 低效寫法 | 高效寫法 |
|---|---|
WHERE SUBSTR(ename,1,3)='SCO' | WHERE ename LIKE 'SCO%' |
WHERE ename = NVL(:name, ename) | WHERE ename LIKE NVL(:name, '%') |
WHERE TRUNC(hiredate)=TRUNC(SYSDATE) | WHERE hiredate BETWEEN TRUNC(SYSDATE) AND TRUNC(SYSDATE)+0.99999 |
WHERE ename||empno='SCOTT7788' | WHERE ename='SCOTT' AND empno=7788 |
WHERE sal+3000<5000 | WHERE sal<2000 |
WHERE sal!=0 | WHERE sal>0 |
原則:讓欄位保持「乾淨」,利用索引範圍掃描。
HAVING 在分組後過濾,需排序聚合;WHERE 在分組前過濾,減少處理行數。
-- 低效:兩次掃描 lookup
WHERE sal = (SELECT MAX(sal) FROM lookup)
AND comm = (SELECT MAX(comm) FROM lookup)
-- 高效:單次掃描
WHERE (sal, comm) = (SELECT MAX(sal), MAX(comm) FROM lookup)
-- 兩次全表掃描
SELECT COUNT(*) FROM emp WHERE status='Y' AND ename LIKE 'SMITH%';
SELECT COUNT(*) FROM emp WHERE status='N' AND ename LIKE 'SMITH%';
-- 一次掃描完成
SELECT COUNT(DECODE(status,'Y','X')) Y_cnt,
COUNT(DECODE(status,'N','X')) N_cnt
FROM emp WHERE ename LIKE 'SMITH%';
多表連接時加上別名(如 e.ename),減少解析時間與歧義錯誤。
-- 低效
WHERE deptno IN (SELECT deptno FROM emp)
-- 高效:半連接,找到即停止
WHERE EXISTS (SELECT NULL FROM emp WHERE emp.deptno = dept.deptno)
NOT IN 觸發全表掃描與排序合併;NOT EXISTS 或外連接 WHERE emp.rowid IS NULL 效能更佳。
一般情況下,直接 JOIN 效能優於子查詢寫法。
一對多查詢時,DISTINCT 需排序去重;EXISTS 只需判斷存在性。
ANALYZE 收集統計資訊建議明確設定 OPTIMIZER_MODE=ALL_ROWS 或 FIRST_ROWS,避免 CHOOSE。
使用綁定變數(:b1)而非字面值,提升語句共享率,減少硬解析。共享池大小需在 init.ora 適當設定。
SELECT *:需查詢資料字典轉換欄位名TRUNCATE 替代 DELETE:不產生 UNDO,釋放空間,不可回滾COMMIT:釋放鎖、UNDO 空間、REDO LOG 緩衝