Hint 是 Oracle 提供給開發者干預優化器決策的機制,可控制優化模式、存取路徑、連接順序、並行度等。本文系統整理 32 類常用 Hint,附帶語法、參數說明與實戰範例。
{DELETE|INSERT|SELECT|UPDATE} /*+ hint [text] [hint[text]]... */
-- 或
{DELETE|INSERT|SELECT|UPDATE} --+ hint [text] [hint[text]]...
語法錯誤時 Oracle 靜默忽略,不報錯。
| Hint | 用途 | 範例 |
|---|---|---|
| ALL_ROWS | 吞吐量優先 | SELECT /*+ALL_ROWS*/ * FROM emp WHERE deptno=10; |
| FIRST_ROWS | 回應時間優先 | SELECT /*+FIRST_ROWS*/ * FROM emp WHERE deptno=10; |
| CHOOSE | 有統計資訊用 CBO,否則 RBO | SELECT /*+CHOOSE*/ * FROM emp; |
| RULE | 強制規則基礎優化 | SELECT /*+RULE*/ * FROM emp; |
| Hint | 用途 | 範例 |
|---|---|---|
| FULL(table) | 全表掃描 | SELECT /*+FULL(e)*/ * FROM emp e; |
| ROWID(table) | ROWID 存取 | SELECT /*+ROWID(emp)*/ * FROM emp WHERE ROWID>='...'; |
| CLUSTER(table) | 叢集掃描 | SELECT /*+CLUSTER*/ * FROM emp, dept WHERE ...; |
| INDEX(table index) | 指定索引掃描 | SELECT /*+INDEX(emp emp_idx)*/ * FROM emp WHERE deptno=10; |
| INDEX_ASC/DESC | 索引升/降序掃描 | SELECT /*+INDEX_DESC(emp pk_emp)*/ * FROM emp; |
| INDEX_COMBINE | 位圖索引合併 | SELECT /*+INDEX_COMBINE(emp idx1 idx2)*/ * FROM emp; |
| INDEX_JOIN | 索引連接存取 | SELECT /*+INDEX_JOIN(emp idx1 idx2)*/ sal, hiredate FROM emp; |
| INDEX_FFS | 快速全索引掃描 | SELECT /*+INDEX_FFS(emp idx_name)*/ * FROM emp; |
| NO_INDEX | 禁止使用指定索引 | SELECT /*+NO_INDEX(emp idx_sal idx_dept)*/ * FROM emp; |
| Hint | 用途 | 範例 |
|---|---|---|
| ORDERED | 依 FROM 子句順序連接 | SELECT /*+ORDERED*/ * FROM a,b,c WHERE a.id=b.id AND b.id=c.id; |
| LEADING(table) | 指定驅動表 | SELECT /*+LEADING(a)*/ * FROM a,b WHERE a.id=b.id; |
| USE_NL(table) | 巢狀迴圈連接 | SELECT /*+USE_NL(b)*/ * FROM a,b WHERE a.id=b.id; |
| USE_MERGE(table) | 排序合併連接 | SELECT /*+USE_MERGE(a,b)*/ * FROM a,b WHERE a.id=b.id; |
| USE_HASH(table) | 雜湊連接 | SELECT /*+USE_HASH(a,b)*/ * FROM a,b WHERE a.id=b.id; |
| DRIVING_SITE(table) | 強制遠端執行 | SELECT /*+DRIVING_SITE(d)*/ * FROM emp, dept@remote d WHERE ...; |
| Hint | 用途 |
|---|---|
| CACHE/NOCACHE | 全表掃描時控制緩衝區 LRU 位置 |
| APPEND/NOAPPEND | 直接路徑插入/傳統插入 |
| REWRITE/NOREWRITE | 啟用/停用查詢重寫 |
| MERGE/NO_MERGE | 視圖合併/不合併 |
| UNION/NO_EXPAND | OR 轉 UNION ALL / 禁止展開 |
| PARALLEL(table, degree) | 指定並行度 |
-- 錯誤寫法:未啟用 PDML,並行提示無效 INSERT /*+parallel(a)*/ INTO target SELECT /*+parallel(a)*/ * FROM source a; -- 正確寫法:Session 層面啟用 PDML ALTER SESSION ENABLE PARALLEL DML; INSERT /*+parallel(target,4)*/ INTO target SELECT /*+parallel(a)*/ * FROM source a;
關鍵點:Oracle 預設不開啟 PDML,DML 語句必須 Session 級啟用;並行非萬能,OLTP 環境需謹慎使用。
SELECT COUNT(*) FROM wid_serv_prod_mon_1100 a
WHERE a.acct_month = 201010
AND NOT EXISTS (
SELECT /*+NO_INDEX(b IDX_W_CDR_MON_SERV_ID_1100)*/ 1
FROM wid_cdr_mon_1100 b
WHERE b.acct_month = 201010
AND b.ANA_EVENT_TYPE_4 IN (...)
AND a.serv_id = b.serv_id
);
善用 Hint 需結合執行計畫分析,盲目添加反而適得其反。