Oracle Hint (提示) 是開發人員與 DBA 影響優化器決策的「直接干預手段」。正確使用 Hint 能繞過優化器缺陷、穩定執行計劃、解決緊急性能問題。本文系統整理 12 類核心 Hint 的語法、適用場景、經典案例及**濫用風險警示**,助你精準施策。
| Hint | 語法 | 作用 | 適用場景 |
|---|---|---|---|
| ALL_ROWS | /*+ ALL_ROWS */ | 目標:最佳吞吐量 (最小化總資源消耗)。CBO 全表掃描、Hash Join、排序合併傾向。 | 批處理、報表、數據倉庫、ETL、無用戶等待的後台作業。 |
| FIRST_ROWS(n) | /*+ FIRST_ROWS(10) */ | 目標:最佳響應時間 (快速返回前 n 行)。CBO 傾向 Nested Loops、Index Range Scan、避免排序/全掃描。 | Web 分頁查詢、交互式應用、OLTP 核心交易 (n=1,10,100)。 |
| CHOOSE | /*+ CHOOSE */ | 有統計信息用 CBO (ALL_ROWS),無統計信息用 RBO。**已廢棄 (10g+),勿用。** | 舊版遷移過渡期。 |
| RULE | /*+ RULE */ | 強制使用基於規則優化器 (RBO)。**已廢棄 (10g+),勿用。** | 極少數 RBO 表現優於 CBO 的歷史系統 (極罕見)。 |
| Hint | 語法 | 作用 | 適用場景與風險 |
|---|---|---|---|
| FULL | /*+ FULL(t) */ | 對表 t 強制全表掃描。 | 小表、無索引、統計信息缺失導致誤用索引、並行全掃描配合 PARALLEL。風險:大表災難。 |
| ROWID | /*+ ROWID(t) */ | 強制通過 ROWID 訪問表 t (需先獲取 ROWID)。 | 極少用,通常配合應用層緩存 ROWID。風險:ROWID 可能因行遷移/重組失效。 |
| CLUSTER | /*+ CLUSTER(t) */ | 強制叢集掃描 (僅適用叢集表)。 | 舊版叢集表極少見。 |
| INDEX | /*+ INDEX(t idx_name) */ | 強制使用索引 idx_name 掃描表 t (Range/Unique/Full/Fast Full)。 | 優化器誤判選擇性、跳過低選擇性索引、測試索引效果。**風險**:索引失效/不可用時報錯/全掃描。 |
| NO_INDEX | /*+ NO_INDEX(t idx_name) */ | 禁止使用指定索引。 | 索引導致計劃劣化、測試無索引基線。 |
| INDEX_FFS | /*+ INDEX_FFS(t idx_name) */ | 索引快速全掃描 (不訪問表塊,僅掃描索引葉塊)。 | 索引包含所有查詢欄位 (覆蓋索引)、統計信息準確。**需配合 INDEX_FILTER?** |
| INDEX_ASC / INDEX_DESC | /*+ INDEX_DESC(t idx_name) */ | 指定索引掃描方向 (避免排序)。 | ORDER BY pk DESC 配合索引降序掃描返回 Top-N。 |
| Hint | 語法 | 作用 | 適用場景 |
|---|---|---|---|
| USE_NL | /*+ USE_NL(t2) */ | 強制 Nested Loops Join (t2 為內表/驅動表)。 | 小結果集驅動大表、內表有高選擇性索引、FIRST_ROWS 目標。 |
| USE_HASH | /*+ USE_HASH(t2) */ | 強制 Hash Join。 | 大表關聯、無合適索引、並行查詢、ALL_ROWS 目標。 |
| USE_MERGE | /*+ USE_MERGE(t2) */ | 強制 Sort Merge Join。 | 已排序數據源、大表關聯、並行查詢、Hash Join 記憶體不足。 |
| LEADING | /*+ LEADING(t1 t2 t3) */ | 指定連接順序 (t1 驅動 t2,結果驅動 t3)。 | 多表關聯優化器誤判驅動表、修復笛卡爾積風險。**最強連接控制 Hint。** |
| ORDERED | /*+ ORDERED */ | 按 FROM 子句順序連接。**不如 LEADING 靈活,勿用。** | 舊版兼容。 |
| SWAP_JOIN_INPUTS | /*+ SWAP_JOIN_INPUTS(t2) */ | 交換 Hash Join 的 Build/Probe 輸入 (Build 端小表進內存)。 | 優化器誤判 Build 端大小、並行 Hash Join 數據傾斜。 |
| Hint | 語法 | 作用 |
|---|---|---|
| PARALLEL | /*+ PARALLEL(t, 8) */ | 指定表 t 並行度 8 (需 Enterprise Edition)。 |
| NO_PARALLEL | /*+ NO_PARALLEL(t) */ | 禁止並行。 |
| PQ_DISTRIBUTE | /*+ PQ_DISTRIBUTE(t, HASH, HASH) */ | 指定並行連接數據分發方式。 |
| APPEND / APPEND_VALUES | /*+ APPEND */ | 直接路徑插入 (繞過緩存、高水位線、無重做最小化)。 |
| NOLOGGING | 非 Hint,屬性。配合 APPEND 減少重做。 | 大批量載入、中間表、可重建數據。 |
| CARDINALITY | /*+ CARDINALITY(t 1000) */ | 告知優化器表 t 結果集基數 1000 行 (修正統計信息偏差)。 |
| OPT_ESTIMATE | /*+ OPT_ESTIMATE(TABLE t SCALE_ROWS=0.1) */ | 11g+ 更強大的基數調整 (SCALE_ROWS, MIN/MAX, JOIN)。 |
| DYNAMIC_SAMPLING | /*+ DYNAMIC_SAMPLING(t 4) */ | 級別 0-10,運行時採樣收集統計信息 (無統計/統計過期表)。 |
| RESULT_CACHE | /*+ RESULT_CACHE */ | 結果集緩存 (11g+,需 RESULT_CACHE_MODE=FORCE 或 Hint)。 |
| QB_NAME | /*+ QB_NAME(main) */ | 為查詢塊命名,供外層/其他 Hint 精準引用 (多層嵌套/視圖合併場景必須)。 |
-- 原 SQL:A(2000行) JOIN B(15萬) JOIN C(18萬)
-- 優化器誤選 A-C Merge Join 產生 3.6億中間集
SELECT /*+ LEADING(a b c) USE_NL(b) USE_NL(c) */ a.*
FROM a, b, c
WHERE a.col_a = b.col_b1
AND b.col_b2 = c.col_c;
解析:LEADING(a b c) 強制 A 驅動 B,再驅動 C。USE_NL 利用 B、C 上的索引。避免 A-C 直接關聯。
SELECT /*+ FIRST_ROWS(10) INDEX_DESC(orders idx_orders_cust_date) */ *
FROM orders
WHERE cust_id = :cust_id
ORDER BY order_date DESC
FETCH FIRST 10 ROWS ONLY;
解析:FIRST_ROWS(10) 告知只需前 10 行。INDEX_DESC 利用 (cust_id, order_date DESC) 索引降序掃描直接返回,避免排序。
INSERT /*+ APPEND PARALLEL(stg_sales, 8) */ INTO stg_sales
SELECT * FROM ext_sales_data;
解析:APPEND 直接寫數據塊 (高水位線以上),PARALLEL 多進程並行。配合 NOLOGGING 表屬性極速載入。
OPT_ESTIMATE 修正基數時使用。USE_NL 和 USE_HASH。優化器忽略衝突 Hint,行為不可預期。-- 1. 10053 事件追蹤 (生成優化器決策日誌,含 Hint 採納/忽略原因)
ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
-- 執行 SQL
-- 關閉
ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT OFF';
-- 2. V$SQL_PLAN.OUTLINE_DATA / OTHER_XML (11g+)
-- 查看實際執行計劃中體現的 Hint (OUTLINE 格式)
-- 3. DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'OUTLINE')
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(sql_id, child_number, 'OUTLINE'));
Oracle Hint 是「手術刀」,精準鋒利但風險自負。掌握 LEADING 控制連接順序、FIRST_ROWS/ALL_ROWS 設定目標、INDEX/NO_INDEX 控制訪問路徑、PARALLEL/APPEND 加速大數據操作、OPT_ESTIMATE/CARDINALITY 修正基數、QB_NAME 定位查詢塊 這幾大核心族群,建立 **Hint 使用登記表 (SQL_ID, Hint清單, 原因, 負責人, 評審日期, 移除計劃)**,在代碼審查、上線驗證、AWR 定期巡檢中強制執行「Hint 必審、必註、必評、必退」四字方針,才能讓 Hint 成為性能優化的加速器而非技術債的製造者。