Hint(提示)是開發者干預 CBO(成本基礎優化器)的手段,指定存取路徑、連接方式、並行度等。但 Hint 非萬靈丹——**錯誤 Hint 會被靜默忽略**,且隨資料變化可能適得其反。本文系統整理 Hint 分類、標準語法、失效機制、常用 Hint 速查表與最佳實務。
{SELECT|INSERT|UPDATE|DELETE} /*+ hint [text] [hint...] */ ...
/*+ 中間**不可有空格**。/*+ RULE */ 外,任何 Hint 皆隱含啟用 CBO;若無統計資訊將用預設值。CBO 若判斷 Hint 會導致**錯誤結果**(而非單純效能差),會直接忽略 Hint。經典案例:
-- 索引鍵允許 NULL,COUNT(*) 不能只掃索引
SELECT /*+ INDEX(t t_ind) */ COUNT(*) FROM t; -- 忽略 Hint,改全表掃描
-- 改為 COUNT(不含 NULL 的欄位) 即可用索引
SELECT /*+ INDEX(t t_ind) */ COUNT(id) FROM t; -- 採用 INDEX FULL SCAN
其他失效情境:Hint 拼寫錯誤、引用不存在索引、語法不符、版本不支援、與其他 Hint 衝突。
| 類別 | 代表 Hint | 用途 |
|---|---|---|
| 優化目標 | ALL_ROWS | 最大吞吐量(預設) |
FIRST_ROWS(n) | 最快回應前 n 列 | |
RULE | 強制 RBO(10g+ 已廢) | |
| 存取路徑 | FULL(t) | 全表掃描 |
INDEX(t idx) | 指定索引掃描 | |
INDEX_ASC/DESC | 索引升/降序範圍掃描 | |
INDEX_FFS(t idx) | 快速全索引掃描 | |
INDEX_SS(t idx) | 索引跳躍掃描(聯合索引非前導欄) | |
NO_INDEX(t idx) | 禁止使用特定索引 | |
| 連接順序/方式 | LEADING(t1 t2) | 指定驅動表順序(建議取代 ORDERED) |
ORDERED | 依 FROM 子句順序連接 | |
USE_NL(t1 t2) | Nested Loops 連接 | |
USE_HASH(t1 t2) | Hash Join 連接 | |
USE_MERGE(t1 t2) | Sort-Merge Join 連接 | |
| 並行/其他 | PARALLEL(t n) | 指定並行度 |
APPEND | 直接路徑插入(載數據) | |
CACHE(t) | 全掃時置於 LRU 熱端 | |
DYNAMIC_SAMPLING(t n) | 動態取樣等級 0-10 |
-- 指定驅動表 + Hash Join + 並行 4
SELECT /*+ LEADING(orders o) USE_HASH(o oi) PARALLEL(oi 4) */
o.order_id, SUM(oi.qty * oi.price)
FROM orders o, order_items oi
WHERE o.order_id = oi.order_id
GROUP BY o.order_id;
DBMS_STATS.GATHER_TABLE_STATS,CBO 多數情況自行最優。EXPLAIN PLAN / DBMS_XPLAN.DISPLAY_CURSOR 確認 Hint 確實生效且效能提升。RULE、AND_EQUAL、STAR、BITMAP、HASH_AJ、MERGE_AJ、NL_SJ、NL_AJ、ORDERED_PREDICATES 等在 10g 標記廢棄,12c+ 可能完全失效,勿用於新系統。
Hint 是手術刀,非萬能鑰。理解 CBO 決策邏輯、掌握 Hint 分類與失效機制、建立「統計優先、Hint 最後、驗證必做、文件留痕」流程,才能在關鍵路徑精準干預、長期受益。