Dictionary Cache命中率低本质是应用层元数据访问缺陷,需查实时值(非AWR平均)、定位dc_objects/dc_users等高miss类型,并分析latch: row cache objects争用源头,优先优化SQL和连接池而非调大shared_pool_size。
dictionary cache 命中率低,不是“调大 shared_pool_size”就能解决的问题——它往往暴露的是应用层元数据访问模式缺陷,而非内存不足。
查当前真实命中率,别只信AWR快照点
AWR报告里那个“Dictionary Cache Hit Ratio”是采样区间平均值,掩盖尖峰。真正要盯的是实时趋势和突变点:
- 运行
SELECT (1 - SUM(getmisses)/NULLIF(SUM(gets),0)) * 100 AS "Row Cache Hit Ratio" FROM v$rowcache;看当前实例瞬时值 - 若该值从 99.2% 骤降至 87%,且时间点与某次部署/脚本上线吻合,基本可锁定源头
- 注意
NULLIF(SUM(gets),0)是必须的,避免除零报错
定位高 miss 的 cache 类型:重点看 dc_objects 和 dc_users
不是所有字典缓存 miss 都一样严重。用这条语句揪出真凶:
SELECT parameter, gets, getmisses, scans, scanmisses FROM v$rowcache WHERE getmisses > 100 ORDER BY getmisses DESC;
重点关注:
-
dc_objects:对象定义(表、视图、同义词)反复解析,常见于硬编码SELECT COUNT(*) FROM dba_tables WHERE table_name = 'X'类检查 -
dc_users:用户权限校验风暴,典型诱因是应用未启用连接池,每个请求用不同用户名连库,或频繁执行ALTER SESSION SET CURRENT_SCHEMA=... -
dc_segments:段信息查询多,可能来自监控脚本每分钟刷一次dba_segments
latch: row cache objects 等待高 ≠ 缓存小
这个 latch 争用高,90% 情况下不是因为 shared_pool_size 不够,而是并发短操作抢同一把锁:
- 查等待强度:
SELECT event, time_waited_micro/1000000 AS sec, waits FROM v$system_event WHERE event = 'latch: row cache objects'; - 查谁在刷字典:
SELECT sql_id, sql_text FROM v$sql WHERE sql_text LIKE '%dba_%' OR sql_text LIKE '%all_%' OR sql_text LIKE '%v$%';—— 很多 GUI 工具、健康检查脚本就藏在这里 - Oracle 12c+ 中,
optimizer_adaptive_features开启时,自适应统计收集也会密集触发dc_users和dc_objects访问,可临时关闭验证影响
优化方向优先级:从应用层往内收
改参数是下策,先堵住源头:
- 禁用无意义的元数据扫描:比如开发写的“表是否存在”逻辑,应改用
user_tables替代dba_tables,或直接捕获ORA-00942 - 强制连接复用:应用必须启用连接池,杜绝每请求换一个用户名;如需切换 schema,改用
ALTER SESSION SET CURRENT_SCHEMA+ 应用角色权限预置,而非靠每次校验 - 慎用隐藏参数:比如
_optimizer_use_feedback=FALSE可缓解自适应特性引发的字典压力,但仅作临时验证,不建议长期开启
最易被忽略的一点:v$rowcache 中的 scans 和 scanmisses 比 gets/getmisses 更能反映“高频低效查询”——比如一个 SELECT * FROM dba_users 扫全表,scans 会飙升,但 gets 可能不高。



















