Hint(提示)是嵌入在 SQL 註解中的特殊指令,用於引導最佳化器選擇特定執行計畫。語法格式:/*+ HINT_NAME([parameters]) */。善用 Hint 可在統計資訊不足、最佳化器判斷失誤時強制指定存取路徑、聯結順序或並行度。
| Hint | 說明 | 範例 |
|---|---|---|
ALL_ROWS | 以成本為基礎,追求最佳吞吐量(全表掃描傾向) | SELECT /*+ ALL_ROWS */ * FROM emp WHERE deptno=10; |
FIRST_ROWS(n) | 以成本為基礎,追求前 n 列最快回應時間 | SELECT /*+ FIRST_ROWS(10) */ * FROM emp ORDER BY hiredate; |
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(e) */ * FROM emp e WHERE ROWID='AAA...'; |
CLUSTER(table) | 叢集掃描(僅叢集表) | SELECT /*+ CLUSTER(e) */ * FROM emp e, dept d WHERE e.deptno=d.deptno; |
INDEX(table [index]) | 索引範圍掃描 | SELECT /*+ INDEX(e emp_idx) */ * FROM emp e WHERE deptno=10; |
INDEX_ASC / INDEX_DESC | 索引升/降序掃描 | SELECT /*+ INDEX_DESC(e pk_emp) */ * FROM emp e WHERE empno>100; |
INDEX_COMBINE | 位圖索引布林組合 | SELECT /*+ INDEX_COMBINE(e idx1 idx2) */ * FROM emp e WHERE sal<5000 AND hiredate>...; |
INDEX_JOIN | 索引聯結(不回表) | SELECT /*+ INDEX_JOIN(e idx_sal idx_hire) */ sal, hiredate FROM emp e WHERE sal<60000; |
INDEX_FFS(table index) | 快速全索引掃描 | SELECT /*+ INDEX_FFS(e emp_name_idx) */ * FROM emp e WHERE deptno=20; |
INDEX_SS / INDEX_SS_ASC / INDEX_SS_DESC | 索引跳躍掃描 | SELECT /*+ INDEX_SS(e comp_idx) */ * FROM emp e WHERE deptno=10; |
| Hint | 說明 | 範例 |
|---|---|---|
USE_NL(table) | 巢狀迴圈聯結,指定表為內部表 | SELECT /*+ ORDERED USE_NL(e) */ * FROM dept d, emp e WHERE d.deptno=e.deptno; |
USE_MERGE(table) | 排序合併聯結 | SELECT /*+ USE_MERGE(e,d) */ * FROM emp e, dept d WHERE e.deptno=d.deptno; |
USE_HASH(table) | 雜湊聯結 | SELECT /*+ USE_HASH(e,d) */ * FROM emp e, dept d WHERE e.deptno=d.deptno; |
| Hint | 說明 | 範例 |
|---|---|---|
ORDERED | 依 FROM 子句順序聯結 | SELECT /*+ ORDERED */ * FROM t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id; |
LEADING(table) | 指定第一個驅動表 | SELECT /*+ LEADING(d) */ * FROM dept d, emp e WHERE d.deptno=e.deptno; |
DRIVING_SITE(table) | 強制在指定站點執行(分散式查詢) | SELECT /*+ DRIVING_SITE(d) */ * FROM emp e, dept@remote d WHERE e.deptno=d.deptno; |
| Hint | 說明 | 範例 |
|---|---|---|
USE_CONCAT | 將 OR/IN-LIST 展開為 UNION ALL | SELECT /*+ USE_CONCAT */ * FROM emp WHERE deptno=10 OR deptno=20; |
NO_EXPAND | 禁止 OR/IN-LIST 展開 | SELECT /*+ NO_EXPAND */ * FROM emp WHERE deptno IN (10,20,30); |
REWRITE / NO_REWRITE | 啟用/停用物化視圖重寫 | SELECT /*+ REWRITE(mv_sales) */ * FROM sales WHERE year=2023; |
MERGE / NO_MERGE | 合併/不合併視圖/子查詢 | SELECT /*+ MERGE(v) */ * FROM emp e, (SELECT deptno, AVG(sal) avg_sal FROM emp GROUP BY deptno) v WHERE e.deptno=v.deptno AND e.sal>v.avg_sal; |
STAR_TRANSFORMATION | 星狀轉換(資料倉儲) | SELECT /*+ STAR_TRANSFORMATION */ * FROM fact f, dim1 d1, dim2 d2 WHERE f.d1_key=d1.key AND f.d2_key=d2.key; |
| Hint | 說明 | 範例 |
|---|---|---|
PARALLEL(table n) | 指定並行度 | SELECT /*+ PARALLEL(e,4) */ * FROM emp e; |
NOPARALLEL | 禁止並行 | SELECT /*+ NOPARALLEL */ * FROM emp; |
APPEND / NOAPPEND | 直接路徑插入/常規插入 | INSERT /*+ APPEND */ INTO target SELECT * FROM source; |
CACHE / NOCACHE | 全掃描時置於/移出 LRU 熱端 | SELECT /*+ FULL(e) CACHE(e) */ * FROM emp e; |
PUSH_PRED / NO_PUSH_PRED:謂詞下推至視圖/子查詢PUSH_SUBQ / NO_PUSH_SUBQ:子查詢提前/延後執行QB_NAME:為查詢區塊命名,配合 @qb_name 精準指定 Hint 作用範圍OPT_PARAM('_param_name' 'value'):會話層級暫時調整隱藏參數DBMS_STATS.GATHER_TABLE_STATS 解決 90% 執行計畫問題,Hint 應為最後手段。EXPLAIN PLAN、DBMS_XPLAN.DISPLAY_CURSOR 對比 Hint 前後計畫與實際執行時間。Hint 是雙面刃:用得好可瞬間解決效能危機,濫用則會隨版本升級、資料分佈變化而失效甚至產生負面影響。建立「統計資訊優先、Hint 輔助、持續監控」的調優文化,才是長久之計。