SELECT 執行三階段模型
Oracle 處理一條 SELECT 語句,內部分為 **Parse (解析) → Execute (執行) → Fetch (提取)** 三個明確階段。理解每階段的內部動作,是 SQL 調優、故障診斷的基礎。
Phase 1: Parse (解析階段) — 最複雜、最耗資源
- 語法檢查:關鍵字拼寫、結構合法性 (如少括號、錯誤子句)。
- 語義檢查:
- 對象是否存在 (查
DBA_TABLES, DBA_VIEWS 等數據字典)
- 列名是否正確 (展開
* 為所有列)
- 權限驗證 (SELECT 權限、角色)
- 共享池查找 (Soft Parse vs Hard Parse):
- 計算 SQL 文本哈希值 (SQL_ID)
- 在 Library Cache 中匹配**完全相同**的可執行游標 (大小寫、空格、註釋、綁定變量名均需一致)
- 命中 → Soft Parse,直接復用執行計劃,**跳過優化器**
- 未命中 → Hard Parse,進入優化器流程
- 優化器生成執行計劃 (Hard Parse 核心):
- 收集統計信息 (表/索引/列/系統)
- 枚舉訪問路徑 (全表掃描、索引範圍掃描、全索引掃描、分區裁剪...)
- 枚舉連接方法 (Nested Loops / Hash Join / Sort Merge Join)
- 枚舉連接順序
- 基於成本模型 (CBO) 計算各路徑 Cost (I/O + CPU)
- 選擇 Cost 最低計劃 → 生成二進制執行代碼 → 存入 Library Cache
- 獲取對象鎖 (DDL 防護):解析期間在對象上獲取
Library Cache Lock/Pin,防止並發 DDL 導致對象定義變更。
Phase 2: Execute (執行階段) — 數據訪問入口
- 啟動執行計劃:按照計劃樹自下而上調用行源函數。
- 緩存檢查 (Buffer Cache):
- 計算所需數據塊的 DBA (Data Block Address)
- 在 Buffer Cache (通過 Cache Buffers Chains 哈希鏈) 查找
- 命中 → Logical Read (Consistent Get / Current Get),**零物理 I/O**
- 未命中 → 發起物理讀請求 (db file sequential/scattered read) → 讀入 Buffer Cache
- 一致性構建 (Consistent Read):若塊版本過新 (SCN > 查詢 SCN),利用 Undo 回滾構建 CR 塊 (Consistent Read)。
- 並行執行 (PX):若計劃含
PX SEND/RECEIVE,協調多進程並行掃描/連接/聚合。
Phase 3: Fetch (提取階段) — 結果集交付
- 從 Buffer Cache 獲取行:行源函數逐行返回 (Row Source Generator)。
- 網絡傳輸:打包為 SDU (Session Data Unit) 經 SQL*Net 發送給客戶端。
- Array Fetch:客戶端
ARRAYSIZE (默認 15/50/100) 決定每次往返返回行數,**增大 ArraySize 可大幅減少網絡往返**。
- 游標關閉:所有行提取完或顯式
CLOSE CURSOR,釋放資源 (PGA、鎖、臨時段)。
關鍵性能指標對應階段
| 指標 | 階段 | 含義 | 優化方向 |
| Hard Parse Count | Parse | 硬解析次數 | 綁定變量、CURSOR_SHARING、會話緩存游標 |
| Library Cache Misses | Parse | 共享池未命中 | 增大 Shared Pool、KGL 模擬、固定計劃 |
| Optimizer Cost/Time | Parse | 優化器估算成本 | 統計信息、Hint、SQL Profile、Baseline |
| Consistent Gets | Execute/Fetch | 一致性讀邏輯 I/O | 索引優化、減少全表掃描、調整 PCTFREE |
| Physical Reads | Execute | 物理 I/O | 緩存命中率、預讀、SSD、表壓縮 |
| Rows Processed / Fetch Calls | Fetch | 處理行數/提取次數 | 增大 ARRAYSIZE、流式處理 |
| SQL*Net Roundtrips | Fetch | 網絡往返次數 | Array Fetch、結果集緩存、就近訪問 |
實戰診斷思路
- 慢在 Parse:Hard Parse 高 → 檢查綁定變量使用率、共享池大小、字面量 SQL 暴增。
- 慢在 Execute:Physical Reads 高 / Consistent Gets 高 → 執行計劃退化、統計信息過期、索引缺失、熱塊競爭。
- 慢在 Fetch:網絡延遲、ArraySize 過小、客戶端處理慢、大結果集分頁無優化。
總結
**Parse = 編譯優化,Execute = 數據訪問,Fetch = 結果交付**。
DBA 日常調優本質上是:**
1. 消除不必要的 Hard Parse (綁定變量、游標共享)
2. 讓 Execute 走最優路徑 (統計信息、索引、分區、Hint、Baseline)
3. 讓 Fetch 高效交付 (ArraySize、流式、分頁優化)**
將三階段模型內化為診斷直覺,是從「看執行計劃」進化為「懂運行機制」的關鍵。