buffer cache扩容应看v$db_cache_advice中estd_physical_reads曲线拐点后斜率明显变平处,如10g→12g降幅骤减即为性价比终点,并需满足粒度对齐、size_factor≥1.0及shared pool free memory≥5%总sga等硬约束。

怎么看 Buffer Cache 是否该扩容
直接看 V$DB_CACHE_ADVICE 里的 ESTD_PHYSICAL_READS 曲线,不是找最低点,而是找“拐点后斜率明显变平”的区间。比如从 8G → 10G 时物理读下降 1200,而 10G → 12G 只降 45,那 10G 就是性价比终点。
注意三个硬约束:
-
SIZE_FOR_ESTIMATE必须对齐V$SGAINFO.GRANULE_SIZE(比如 4MB),Oracle 不会分配非粒度整数倍的值 -
SIZE_FACTOR必须 ≥ 1.0,小于 1 是压缩模拟,不能当扩容依据 - 扩容后要查
V$SGASTAT中shared pool的free memory是否仍 ≥ 5% 总 SGA,否则可能引发ORA-04031
Shared Pool 内存紧张的典型信号
别等报错才行动。V$SGASTAT 里 shared pool 下 free memory 持续低于 100MB(小系统)或 5% 总 SGA(大系统),就是危险信号。
配合看这两个指标:
-
V$SQLAREA.VERSION_COUNT > 1的 SQL 占比超过 15%,说明大量 SQL 因绑定变量窥探或 hint 导致无法共享,硬解析飙升 - AWR 报告中 “latch free” 等待事件上升,尤其集中在
library cache lock或library cache pin -
V$SGASTAT中sql area和PL/SQL db object cache占比异常高,但free memory极低
SGA_TARGET 自动调优时的常见误操作
设了 SGA_TARGET 后手动再调 DB_CACHE_SIZE 或 SHARED_POOL_SIZE,等于关掉自动 rebalance。Oracle 会锁死你设的组件值,不再动态调整。
正确做法只有两种:
- 纯自动:只设
SGA_TARGET,其他组件参数留空或设为 0 - 半手动:用
ALTER SYSTEM SET SGA_TARGET = <new_value></new_value>调总大小,让 Oracle 自己按负载重新分
另外,V$SGA_TARGET_ADVICE 的 ESTD_DB_TIME_FACTOR 1,说明当前 SGA 已足够,再扩反而增加管理开销。
为什么 DB_CACHE_SIZE 加了,物理读反而上升
这不是内存没起作用,而是优化器行为变了。Buffer cache 变大后,CBO 认为全表扫描的逻辑读成本更低,把原本走索引的 SQL 改成 TABLE ACCESS FULL,触发更多磁盘读。
验证步骤很直接:
- 在 AWR 中比对 “SQL ordered by Reads” 和 “SQL ordered by Gets”,如果 top 物理读 SQL 同时也是 top 逻辑读 SQL,大概率是执行计划偏移
- 查
V$SQL_PLAN对应 SQL 的OPERATION字段,确认是否从INDEX RANGE SCAN变成了TABLE ACCESS FULL - 临时加
ALTER SYSTEM SET "_optimizer_ignore_hints"=TRUE测试,排除 hint 强制导致的异常
真正影响缓存效率的,从来不是“有没有内存”,而是“内存有没有被有效利用”。Buffer cache 大小只是杠杆,底下的 SQL 质量和执行路径才是支点。











