首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle FIRST_ROWS vs FIRST_ROWS(n) 差異實測:代價基礎與規則基礎的抉擇

     編輯:Oracle 資料庫基礎

前言

FIRST_ROWS (無參數) 與 FIRST_ROWS(n) (9i 引入) 雖同屬「優先回應前幾列」導向,但內部優化邏輯截然不同。本文透過實測案例揭示兩者在執行計畫選擇上的關鍵差異。

核心差異

Hint優化基礎行為特徵
FIRST_ROWS**混合模式**:代價基礎 + 大量規則啟發式傾向使用索引、Nested Loops,甚至忽略統計資訊選擇 Domain Index 等特殊索引
FIRST_ROWS(n)**純代價基礎 (CBO)**依統計資訊計算前 n 列成本,選擇真正代價最低路徑 (可能為全表掃描 + Hash Join)

實測場景重現

環境建置

CREATE TABLE t (id NUMBER PRIMARY KEY, name VARCHAR2(30), docs VARCHAR2(4000));
INSERT INTO t SELECT rownum, object_name, owner||' '||object_type||' '||object_name FROM dba_objects;
CREATE INDEX ind_t_name ON t(name);
CREATE INDEX ind_t_docs ON t(docs) INDEXTYPE IS CTXSYS.CONTEXT; -- 全文索引
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T', METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE 100');
EXEC DBMS_STATS.GATHER_INDEX_STATS(USER, 'IND_T_DOCS');

查詢:全文搜尋 + 精確過濾 + 評分排序

SELECT * FROM t
WHERE CONTAINS(docs, 'SYS', 1) > 0
AND name = 'DUAL'
ORDER BY SCORE(1);

執行計畫對比

-- 無 Hint (CHOOSE 模式,有統計資訊走 CBO)
-- 選擇:INDEX RANGE SCAN (IND_T_NAME) → TABLE ACCESS BY ROWID → SORT ORDER BY
-- Cost = 5

-- FIRST_ROWS Hint
SELECT /*+ FIRST_ROWS */ * FROM t ...
-- 選擇:DOMAIN INDEX (IND_T_DOCS) → TABLE ACCESS BY ROWID
-- Cost = 2643  <-- 規則啟發式誤判全文索引優先,實際極慢

-- FIRST_ROWS(1) Hint
SELECT /*+ FIRST_ROWS(1) */ * FROM t ...
-- 選擇:INDEX RANGE SCAN (IND_T_NAME) → TABLE ACCESS BY ROWID → SORT ORDER BY
-- Cost = 5   <-- 代價基礎正確評估,同預設 CBO

深度解析

  • FIRST_ROWS 保留舊版 RBO 邏輯:發現 CONTAINS 條件 → 規則認定「Domain Index 適合全文」→ 強制使用,忽略 name='DUAL' 高選擇性 B-tree 索引。
  • FIRST_ROWS(n) 完全依賴統計資訊:計算 name='DUAL' 過濾後僅 1 列,再做全文評分排序成本極低 → 選擇 B-tree 索引。
  • 這也是 Oracle 預設 OPTIMIZER_MODE=ALL_ROWS 而非 FIRST_ROWS 的原因:避免規則啟發式導致不可預測的劣質計畫。

最佳實務建議

  1. **永遠使用 FIRST_ROWS(n)** (n 為預期顯示列數,如 10、20、100),拒絕無參數 FIRST_ROWS。
  2. 確保統計資訊完整 (含直方圖),讓 CBO 能精準估算前 n 列成本。
  3. 互動式分頁查詢:/*+ FIRST_ROWS(100) */ 配合分頁範本 (見 上一篇) 效果最佳。
  4. 批次/報表查詢:維持 ALL_ROWS 或 /*+ ALL_ROWS */ 追求總吞吐量。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved