字典缓存命中率低于95%需结合趋势与关联事件定位,重点查v$rowcache中dc_objects、dc_users等高miss类型,并分析latch: row cache objects争用及高频数据字典查询。
Dictionary Cache Hit Ratio 低于 95% 怎么快速定位问题
字典缓存(dictionary cache,也叫 row cache)命中率低,通常意味着频繁访问数据字典视图(如 dba_tables、all_objects)时反复触发物理读或递归 sql 解析,背后往往是低效的元数据操作或权限/对象检查风暴。
关键不是看“是否低于 95%”,而是看变化趋势和关联事件——比如某次部署后该值从 99.2% 掉到 87%,同时 latch: row cache objects 等待飙升,那基本可以锁定问题。
- 查当前命中率(避免只信 AWR 报告里一个快照点):
SELECT (1 - SUM(getmisses)/NULLIF(SUM(gets),0)) * 100 AS "Row Cache Hit Ratio" FROM v$rowcache;
- 重点看哪些 cache 类型在 miss:
SELECT parameter, gets, getmisses, scans, scanmisses FROM v$rowcache WHERE getmisses > 100 ORDER BY getmisses DESC;
—— 尤其关注dc_objects(对象定义)、dc_users(用户信息)、dc_segments(段信息) - 如果
dc_usersmiss 高,先检查应用是否用大量不同用户名连接(比如未启用连接池),或存在硬编码的ALTER SESSION SET CURRENT_SCHEMA=...导致反复校验用户权限
latch: row cache objects 等待高,一定是字典缓存不够吗
不是。这个 latch 是保护整个 row cache 内存结构的串行化机制,争用高 ≠ 缓存小,更常见的是“高频短操作”引发的并发冲突,比如大量并发会话同时解析含同义词、视图、或依赖动态权限检查的 SQL。
典型误判:看到 latch: row cache objects 平均等待时间长,就去调大 shared_pool_size——但往往无效,因为问题不在内存不足,而在 latch 获取路径太热。
- 确认是不是 latch 争用主导:
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 '%v$%' OR sql_text LIKE '%dba_%' OR sql_text LIKE '%all_%';
—— 很多监控脚本、GUI 工具、甚至开发写的“检查表是否存在”的 PL/SQL 块,都在后台狂刷DBA_OBJECTS - 注意 Oracle 12c+ 中,
optimizer_adaptive_features开启时,某些自适应统计收集也会触发密集的dc_users和dc_objects访问,可临时关闭验证影响
Parse CPU to Parse Elapsd % 只有 53.78%,和字典缓存有关吗
有关,而且是强信号。这个指标低,说明 SQL 解析过程大量时间花在等待上(比如等 row cache objects latch、或等 library cache latch),而不是真正在 CPU 上做语法/语义分析。
它不像 Buffer Hit % 那样能直接对应到某个组件大小,但它像一个“解析流水线卡顿报警灯”——尤其当它和 Library Hit %、Row Cache Hit Ratio 同时异常时,基本可断定是共享池内元数据争用或递归调用链过深。
- 不要孤立看该值:对比 AWR 中同一时段的
parse count (hard)和parse time elapsed,若后者远高于前者 × 单次平均解析耗时,说明有阻塞 - 检查是否有大量
SELECT ... FROM DUAL或EXISTS (SELECT 1 FROM DBA_ROLES)类语句——它们看似简单,但每次执行都需完整走一遍字典对象查找流程 - Oracle 19c 起,
_optimizer_use_feedback默认开启,某些计划反馈机制会隐式触发多次dc_objects查询,可设为FALSE观察是否缓解
为什么改了 shared_pool_size,字典缓存表现没变化
因为 v$rowcache 不是独立内存池,它完全位于 shared_pool 内部,且 Oracle 对它的分配不按“预分配块”方式管理,而是随需动态从 shared pool 的 free list 中切小 chunk。增大 shared_pool_size 只是提供更多碎片空间,并不能减少 latch 争用或提升热点条目的缓存稳定性。
真正影响字典缓存效率的,是访问模式是否可预测、是否被重复利用,而不是绝对内存大小。
- 优先做减法:禁用不必要的审计(
audit_trail=NONE)、停掉非必要数据字典查询类监控(比如每 5 秒查一次DBA_FREE_SPACE) - 对高频访问的字典视图,考虑建物化视图 + 定时刷新,把
SELECT COUNT(*) FROM DBA_SEGMENTS这类重操作离线化 - 确认是否用了绑定变量:未绑定的动态 SQL(如
'SELECT * FROM ' || table_name)会导致每次 table_name 不同,都要重新查dc_objects,无法复用结果
最常被忽略的一点:row cache latch 争用经常藏在“正常业务 SQL”背后——比如一条 UPDATE 触发了 3 层触发器,每层都查 USER_TAB_COLUMNS 做列校验,这种嵌套递归调用不会出现在 Top SQL 里,但会持续推高 row cache objects 等待。

















