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

Oracle 執行計劃「無私」健壯性:B-Tree 索引與 NOT NULL 約束的優化智慧

     編輯:Oracle 教學

Oracle 執行計劃「無私」健壯性:B-Tree 索引與 NOT NULL 約束的優化智慧

Oracle 優化器會在開發者給出錯誤 Hint 時仍選擇正確執行計劃,這種「無私」特性體現了資料庫核心邏輯的健壯性。本文透過一個簡單實驗,展示 B-Tree 索引不存儲 NULL 值的特性,如何導致全表掃描而非索引掃描,以及加上 NOT NULL 約束後優化器如何果斷轉向索引快速全掃描,甚至允許 Hint 生效。

實驗環境

  • 測試表 TBL_PLAN,欄位 ID NUMBER
  • 收集統計資訊
  • 建立 B-Tree 索引 IDX_TBL_PLAN_ID ON TBL_PLAN(ID)

階段 1:無 NOT NULL 約束

SELECT ID FROM TBL_PLAN;

執行計劃: TABLE ACCESS FULL TBL_PLAN (全表掃描)

即使加上 Hint:

SELECT /*+ INDEX(TBL_PLAN IDX_TBL_PLAN_ID) */ ID FROM TBL_PLAN;

結果: 仍為全表掃描,Hint 被忽略。

核心原因

B-Tree 索引不存儲完全為 NULL 的鍵值。 雖然表中實際無 NULL,但優化器僅根據中繼資料 (欄位定義允許 NULL) 判斷:若從索引讀取,可能遺漏 NULL 行,導致結果錯誤。為保證正確性,優化器拒絕使用索引,寧選全表掃描。

階段 2:加上 NOT NULL 約束

ALTER TABLE TBL_PLAN MODIFY (ID NOT NULL);

相當於將索引轉為「不含 NULL」的語義保證。

再次查詢

SELECT ID FROM TBL_PLAN;

執行計劃: INDEX FAST FULL SCAN IDX_TBL_PLAN_ID (索引快速全掃描) —— 最佳路徑!

加上 Hint 測試

SELECT /*+ INDEX(TBL_PLAN IDX_TBL_PLAN_ID) */ ID FROM TBL_PLAN;

結果: 此時 Hint 生效,執行計劃顯示 INDEX RANGE SCAN (或 INDEX FULL SCAN),優化器尊重開發者意圖。

總結與啟示

啟示:

  1. 正確的約束定義是優化器做最佳決策的前提:NOT NULL、PRIMARY KEY、UNIQUE、CHECK 等約束不僅是業務規則,更是統計資訊的重要輸入。
  2. 優化器「無私」於保護正確性:即使開發者給錯 Hint,優化器也會拒絕可能產生錯誤結果的路徑。
  3. 應用系統同樣應具備這種健壯性:在不確定或衝突時,選擇安全、正確的預設行為,而非盲目執行指令。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景執行計劃Hint 效果原因
可 NULL 欄位 + B-Tree 索引 全表掃描 忽略 索引可能遺漏 NULL 行,優化器保正確性
NOT NULL 欄位 + B-Tree 索引 索引快速全掃描 生效 語義保證無 NULL,索引安全可用