硬解析 是 Oracle SQL 執行的最大效能殺手之一。首次執行查詢時,Oracle 需遍歷數十個數據字典表獲取元資料。本文揭示硬解析涉及的 16 張核心字典表、59 次查詢細節、Consistent Gets/Physical Reads 實測對比、Shared Pool LRU 淘汰影響、Session Cursor Cache 軟軟解析機制。
| 字典表 | 查詢次數 | 用途 | 常駐記憶體 |
|---|---|---|---|
| ACCESS$ | 1 | 依賴物件對父物件的權限 | 是 |
| CCOL$ | 10 | 約束欄位具體資料 | 是 |
| CDEF$ | 3 | 約束定義資料 | 是 |
| COL$ | 1 | 表欄位具體資料 | 否 (非永久駐留) |
| DEPENDENCY$ | 1 | 物件間依賴關係 | 否 |
| HIST_HEAD$ | 12 | 直方圖頭部資料 | 是 |
| HISTGRM$ | 3 | 直方圖規格 | 是 |
| ICOL$ | 6 | 索引欄位 | 是 |
| IND$, IND_STATS$ | 1 | 索引、索引統計資訊 | 是 |
| OBJ$ | 8 | 物件定義 | Dictionary Cache |
| OBJAUTH$ | 2 | 表授權 | 是 |
| SEG$ | 7 | 所有段映射 | 是 |
| SYN$ | 1 | 同義詞 | 是 |
| TAB$, TAB_STATS$ | 1 | 表、表統計資訊 | 是 |
| USER$ | 2 | 用戶定義 | 是 |
總計:59 次查詢。標註「否」的表 (COL$, DEPENDENCY$) 不永久駐留 Dictionary Cache,可能觸發額外 Physical Read。
-- 測試查詢
SELECT * FROM ttest WHERE object_id = 1000;
-- 環境準備
SET AUTOTRACE TRACEONLY STATISTICS
| 場景 | Consistent Gets | Physical Reads | 解析類型 | CPU/閂鎖影響 |
|---|---|---|---|---|
| 首次執行 (冷啟動) | 230 | 226 | 硬解析 | 佔用 1 CPU 核心,大量 Library Cache/Row Cache 閂鎖 |
ALTER SYSTEM FLUSH SHARED_POOL 後 | 298 | 6 | 硬解析 | 字典資訊部分仍在 Buffer Cache,但 Shared Pool 需重建 |
| 完全緩存後 (再次執行) | 230 | 0 | 軟解析 | 零 Physical Read,最小 CPU/閂鎖 |
| 層級 | 觸發條件 | 開銷 | 關鍵參數 |
|---|---|---|---|
| 硬解析 | Shared Pool 無匹配 Cursor (SQL 文本、綁定變數型別、環境不同) | 最高 (59+ 字典查詢、語法/語義檢查、優化器生成計畫) | CURSOR_SHARING, SHARED_POOL_SIZE |
| 軟解析 | Shared Pool 存在匹配 Cursor (Library Cache Hit) | 低 (僅語法/語義輕量檢查、綁定變數檢查) | SESSION_CACHED_CURSORS |
| 軟軟解析 | Session Cursor Cache 命中 (Client 端緩存 Cursor 狀態) | 極低 (繞過 Library Cache 查找,直接復用 Session 級 Cursor) | SESSION_CACHED_CURSORS (預設 50,建議 200-500) |
WHERE id = :b1 而非 WHERE id = 1000,實現 Cursor SharingSHARED_POOL_SIZE 容納熱門 SQL 計畫,減少 LRU 淘汰ALTER SESSION SET SESSION_CACHED_CURSORS=300 或 SPFILE 設定DBMS_SHARED_POOL.KEEP 釘住核心 SQL,或使用 SQL Plan Baseline-- 實例級硬解析率
SELECT
(1 - (session cursor cache hits) / (parse count (total))) * 100 AS hard_parse_pct
FROM v$sysstat
WHERE name IN ('session cursor cache hits', 'parse count (total)');
-- 高硬解析 SQL 識別
SELECT sql_text, parse_calls, executions,
ROUND(parse_calls/executions, 2) AS parse_per_exec
FROM v$sqlarea
WHERE executions > 0 AND parse_calls > executions * 1.5
ORDER BY parse_calls DESC;
硬解析是「必要之惡」,目標不是消除 (首次必經),而是通過綁定變數、Cursor Cache、Shared Pool 適度配置,將硬解析率控制在 < 5%,軟軟解析佔比 > 80%,構建高併發下的穩定解析引擎。