execute to parse % 低于 40% 就需干预,核心是改 sql 使用绑定变量并调优 session_cached_cursors 和客户端 pscache;须结合 parse cpu to parse elapsd % 分析原因,避免误用 cursor_sharing=force。

Execute to Parse % 低于 40% 就该动手了,不是等它跌破 20% 才干预。这个值低本身不报警,但持续偏低(尤其在业务高峰段)基本等于应用层漏了绑定变量,硬解析正在吃 CPU 和 shared pool latch。优化核心就两条:改 SQL 用绑定变量,调客户端缓存参数——别碰 cursor_sharing=force,它带来的 bug 比收益多。
怎么看 Execute to Parse % 是否真有问题
别只盯一个数字。AWR 报告里 Execute to Parse % 在 Instance Efficiency Percentages 区域,必须和 Parse CPU to Parse Elapsd % 一起看:
- 如果
Execute to Parse %是 29.76,但Parse CPU to Parse Elapsd %接近 100%,说明解析逻辑本身在抢 CPU,得查 SQL 文本里有没有WHERE id = 123这种字面量 - 如果
Execute to Parse %是 29.76,但Parse CPU to Parse Elapsd %只有 15%,那问题不在解析耗时,而在解析太频繁——大概率是游标反复进出共享池,session_cached_cursors或客户端 PSCache 不够 - 刚重启数据库后该值暴跌是正常的,冷启动阶段全库硬解析,别拿首份报告当依据
从 AWR 报告里快速定位高解析 SQL
翻到 SQL Statistics → SQL ordered by Parse Calls 部分,重点不是找 Parse Calls 最高的那条,而是找那些 Parse Calls 和 Executions 数量级接近的 SQL:
- 比如一条 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' - 如果
executions = 1但parse_calls > 1,说明这条语句被硬解析后很快被挤出共享池,是 shared pool 碎片或游标未缓存的信号 - 如果
sql_text里出现大量WHERE status = 'ACTIVE'、AND create_time > TO_DATE('2026-09-15', 'YYYY-MM-DD')这类写死值,就是绑定变量缺失的铁证
绕不开的两个关键参数调整
应用层改 SQL 是根治手段,但上线周期长;先调参能快速缓解。注意:这两个参数必须配合使用,单调一个效果有限:
- 数据库端:
session_cached_cursors建议设为 100(默认常是 0 或 20)。执行:ALTER SYSTEM SET session_cached_cursors = 100 SCOPE=SPFILE,然后重启实例 - 应用端(以 Druid 为例):打开 PreparedStatement 缓存,配置
poolPreparedStatements=true和maxPoolPreparedStatementPerConnectionSize=100 - 验证是否生效:查
v$parameter确认参数已加载;再运行SELECT 'session_cached_cursors' PARAMETER, LPAD(VALUE,5) VALUE, DECODE(VALUE,0,'n/a', TO_CHAR(100*USED/VALUE,'990')||'%') USAGE FROM ...,看 USAGE 是否低于 80% - 别碰
open_cursors:它控制的是每个会话最多能打开多少游标,和解析复用无关;盲目调大反而可能掩盖真实问题
为什么不能开 cursor_sharing=force
这个参数会让 Oracle 自动把字面量替换成绑定变量,听起来很美,但实际踩坑无数:
- 它破坏执行计划稳定性:同一条 SQL 因不同字面量值触发不同执行路径,
ACS(自适应游标共享)可能跟不上,导致子游标爆炸 - 对
TO_DATE、NLS_DATE_FORMAT等依赖会话级 NLS 参数的语句,可能生成错误的执行计划 - Oracle 官方文档明确标注该参数为“legacy compatibility feature”,19c 已标记为 deprecated
- 真正该做的是让开发改代码——把
WHERE name = 'Alice'改成WHERE name = :name,而不是靠数据库兜底
最易被忽略的一点:Execute to Parse % 是倒推值,95% 表示每 100 次执行只解析 5 次;80% 就意味着每 100 次执行要解析 20 次。很多人误以为“只要没报错就没事”,其实当它稳定在 30–40% 区间时,shared pool latch 争用已经悄然升高,只是还没触发明显等待事件而已。











