硬解析比例过高是cpu被反复榨干的直接原因,每次硬解析需重走语法检查、权限校验和执行计划生成,单次耗时0.5–2ms,高并发下极易导致cpu满载、library cache latch争用飙升。
硬解析比例过高不是“慢”的表象,而是cpu被反复榨干的直接原因——每次硬解析都得重走一遍语法检查、权限校验、执行计划生成,纯cpu密集型操作,不读磁盘也卡死。
硬解析一次到底吃多少CPU
实测数据:单次硬解析平均消耗 0.5–2ms CPU时间。看似微小,但乘上并发量就致命:
- 若系统
1000 tps,且 90% SQL 未用绑定变量 → 每秒新增约900次硬解析 - 仅解析环节就吃掉
450ms+CPU 时间/秒 → 相当于一个逻辑核全天候满载 -
v$sqlarea.parse_calls与executions比值接近1,就是典型信号(每执行一次就解析一次)
AWR里“Parse Time”为什么看起来虚高
SQL Parse Time 在 AWR 中统计的是硬解析 + 软解析总耗时,但它不区分类型。而真实瓶颈 90%+ 都在硬解析上:
- 大量字面量 SQL(如
WHERE id = 1001、WHERE id = 1002)被 Oracle 当作不同语句处理 - 每条都触发独立硬解析 →
library cache latch争用飙升 → CPU 狂转,但没干实际业务 -
Parse CPU和Parse Elapsed差值极小,说明不是 I/O 卡住,是纯计算堵死
别只盯着 shared_pool_size 加内存
盲目增大 shared_pool_size 只会让硬解析更隐蔽,不是解决问题,是掩盖问题:
- 硬解析照旧发生,只是共享池淘汰变慢 →
v$sgastat里free memory长期低于50MB,其实是 SQL 太散,不是内存不够 - 优先确认
cursor_sharing是否设为FORCE(开发环境慎用,可能改执行计划) - 查
v$sql的sql_text字段,看是否有:var_name占位符;或用DBMS_XPLAN.DISPLAY_CURSOR(sql_id, child_number)看Peeked Binds部分
session_cached_cursors 不够也会加剧硬解析压力
这个参数控制每个会话能缓存多少游标句柄,默认 50,查出来使用率 100% 就得调:
- 执行
SELECT 'session_cached_cursors' PARAMETER, LPAD(VALUE, 5) VALUE, DECODE(VALUE, 0, ' n/a', TO_CHAR(100 * USED / VALUE, '990') || '%') USAGE FROM ...确认使用率 - 设为
400是常见经验值,但需配合ALTER SYSTEM SET session_cached_cursors=400 SCOPE=SPFILE+ 重启才生效 - 注意:
open_cursors也要同步检查,避免因游标总数超限触发隐式关闭再硬解析
真正难的不是调参,是让所有 SQL 都带绑定变量——哪怕 ORM 自动生成的语句,也要确认它没拼接字面量;一旦漏掉几条高频 SQL,整个优化就前功尽弃。











