awr报告中可通过execute to parse %是否持续低于90%(位于instance efficiency percentages部分)初步判断绑定变量使用不佳,再结合sql ordered by parse calls中parse_calls/executions比值>0.1及sql_text含字面量等特征交叉验证。
能直接识别,但不是靠“报告里写了没用绑定变量”这种提示——awr本身不标注绑定状态,得靠指标+sql文本特征交叉验证。
看 Execute to Parse % 是否持续低于 90%
这个值在 AWR 报告的 Instance Efficiency Percentages 表格里,不用算,Oracle 已算好。它本质是「每执行 100 次,只解析几次」的倒推值:
- 95% → 每 100 次执行仅解析 5 次,游标复用良好
- 80% → 每 100 次执行要解析 20 次,已偏高
- 1.40%(如某客户报告)→ 几乎每次执行都在硬解析,绑定变量大概率大面积缺失
连续几份高峰时段报告都低于 90%,基本可锁定是应用层问题;如果仅单次暴跌,需结合 ASH 看是否由游标失效或子游标爆炸触发。
查 SQL ordered by Parse Calls 里的高频解析语句
翻到 AWR 报告的 SQL Statistics → SQL ordered by Parse Calls 部分,重点盯前 5 条中那些 parse_calls 和 executions 接近的 SQL:
-
parse_calls = 12000,executions = 15000→ 比值 ≈ 0.8,说明大量重复硬解析 - 复制该
sql_id查v$sql:SELECT sql_text, executions, parse_calls FROM v$sql WHERE sql_id = 'xxx' - 若
sql_text中含WHERE id = 123这类字面量,而非WHERE id = :b1,就是绑定缺失的铁证 - 若
executions = 1但parse_calls > 1,说明语句被反复硬解析后挤出共享池,是 shared pool 碎片化信号
用 DBA_HIST_SQLSTAT 算 parse_ratio 排序
AWR 不存解析类型标记,但 DBA_HIST_SQLSTAT 有 parse_calls 和 executions 字段,可间接反映复用程度:
SELECT sql_id, sql_text, parse_calls, executions,
ROUND(parse_calls / NULLIF(executions, 0), 2) parse_ratio
FROM dba_hist_sqltext t
JOIN dba_hist_sqlstat s USING (sql_id)
WHERE s.snap_id BETWEEN &begin_snap AND &end_snap
AND s.parse_calls > 50
AND s.executions > 0
ORDER BY parse_ratio DESC, s.parse_calls DESC;
parse_ratio > 0.9 的 SQL 基本等于没重用游标。注意过滤掉 SELECT * FROM v$session 这类 DBA 工具语句——它们本就不该进库缓存。
为什么有些 SQL 在 AWR 里根本找不到?
不是它没跑,而是没被采样进快照——topnsql 参数卡住了入口:
-
topnsql只保留每个快照周期内按elapsed_time排名前 N 的 SQL,改了参数只对新快照生效 - 即使设为 100,若目标 SQL 在 60 分钟窗口内执行时间短、逻辑读少,或与其它 SQL 性能差距不明显,仍会被截断
- 字面量未替换为绑定变量,会导致相同逻辑的 SQL 被视为多条,稀释单条排名权重
- 验证是否生效:别只盯 AWR HTML 报告的 “Top SQL”,去
DBA_HIST_SQLSTAT查sql_id是否存在
真正难的不是调高 topnsql,而是让目标 SQL 在那个 60 分钟窗口里“脱颖而出”。轻量 OLTP 语句再怎么调参也难挤进 Top 榜单——这时候该切到 V$ACTIVE_SESSION_HISTORY 抓实时采样,或开 SQL Trace 定向捕获。











