反模式: 多條 SQL 分別統計不同部門
SELECT COUNT(*), SUM(sal) FROM emp WHERE deptno=20 AND ename LIKE 'SMITH%';
SELECT COUNT(*), SUM(sal) FROM emp WHERE deptno=30 AND ename LIKE 'SMITH%';
優化: 單次掃描搭配條件彙總
SELECT
COUNT(DECODE(deptno, 20, 'X')) AS d20_cnt,
COUNT(DECODE(deptno, 30, 'X')) AS d30_cnt,
SUM(DECODE(deptno, 20, sal, 0)) AS d20_sal,
SUM(DECODE(deptno, 30, sal, 0)) AS d30_sal
FROM emp
WHERE ename LIKE 'SMITH%';
註:DECODE 回傳 NULL 時 SUM 會忽略,故 ELSE 宜給 0 而非 NULL。
利用 DUAL 與 OUTER JOIN 將多個單列查詢合為一:
SELECT e.ename, d.dname, c.cat_name
FROM emp e, dept d, category c, dual x
WHERE NVL('X', x.dummy) = NVL('X', e.rowid(+))
AND NVL('X', x.dummy) = NVL('X', d.rowid(+))
AND NVL('X', x.dummy) = NVL('X', c.rowid(+))
AND e.empno(+) = 1234
AND d.deptno(+) = 10
AND c.cat_type(+) = 'RD';
權衡: 減少網路往返與解析開銷,但降低可讀性,視情況使用。
利用 ROWID 保留最小/最大值:
DELETE FROM emp e
WHERE e.rowid > (SELECT MIN(x.rowid) FROM emp x WHERE x.empno = e.empno);
| 特性 | DELETE | TRUNCATE |
|---|---|---|
| 觸發 Trigger | 是 | 否 |
| 產生 UNDO/REDO | 大量 | 極少 (僅資料字典) |
| 可 Rollback | 是 | 否 (DDL 隱含 COMMIT) |
| High Water Mark | 不重設 | 重設 |
| 速度 | 慢 | 極快 |
適用: 清空整張表、重建測試資料、ETL 階段性清空。
COMMIT 釋放:
注意: 交易完整性優先,不可為效能犧牲資料一致性。批次作業中每 N 筆 COMMIT 一次為宜。