默认缓冲池无法阻止表块老化,因其采用统一LRU算法管理所有块,大表全表扫描会挤出高频小表块;而KEEP池需配置DB_KEEP_CACHE_SIZE、对象属本地表空间、且不能是集群表或回滚段。

为什么默认缓冲池无法阻止表块老化
因为 DEFAULT 缓冲池使用统一的 LRU 算法管理所有块,访问频率低但体积大的表(比如历史归档表)一旦被全表扫描,就会把高频访问的小表块大量挤出缓存。这不是“不够内存”,而是“缓存策略不匹配”。Oracle 不会因为你查过一次就记住这个表重要——它只看最近谁被访问过、谁最久没被碰过。
配置 KEEP 池前必须确认的三件事
Keep 池不是开箱即用的功能,它依赖显式配置和对象级绑定:
- 实例参数
DB_KEEP_CACHE_SIZE必须设为非零值(例如DB_KEEP_CACHE_SIZE = 100M),否则KEEP子句会被静默忽略 - 目标对象(如表、索引)必须是本地管理表空间(
EXTENT MANAGEMENT LOCAL)中的段,字典管理表空间不支持BUFFER_POOL子句 - 不能对集群表(
CLUSTER TABLE)、回滚段或表空间本身指定BUFFER_POOL,否则报错ORA-02205: only SELECT and ALTER privileges are allowed
如何把一张小维度表固定进 KEEP 池
典型场景:员工部门表 DEPT 全量加载后几乎只读,且每次查询都需关联,必须常驻内存。
执行以下两步(顺序不可颠倒):
- 修改段属性:
ALTER TABLE scott.dept STORAGE (BUFFER_POOL KEEP); - 确保该表所在表空间未启用
FORCE LOGGING(否则可能绕过缓存策略);可通过SELECT force_logging FROM dba_tablespaces WHERE tablespace_name = 'USERS';验证
注意:KEEP 优先级高于 NOCACHE,即使表上已有 NOCACHE,只要加了 STORAGE (BUFFER_POOL KEEP),块仍会进入 KEEP 池。
Recycle 池适合哪些对象?怎么避免误伤热数据
Recycle 池专为“大而冷”的对象设计,比如日志流水表、ETL 中间暂存表。但它不是“丢弃池”——如果错误地把主业务表放进去,会导致频繁物理读,响应时间陡增。
判断是否适用 Recycle 池的关键指标:
- 单次全表扫描后基本不再访问(
v$segment_statistics中logical reads增长缓慢,但physical reads高) - 对象大小超过
DB_CACHE_SIZE的 10%(例如缓存 800MB,表 100MB+) - 没有被任何物化视图日志或复制进程依赖(Recycle 池中块老化更快,可能影响变更捕获)
操作示例:ALTER TABLE ops.log_archive STORAGE (BUFFER_POOL RECYCLE);,但务必先在测试库验证 SELECT /*+ FULL(t) */ COUNT(*) FROM ops.log_archive t; 是否真能接受后续的磁盘 I/O 波动。
Keep 和 Recycle 池的真正难点不在配置命令,而在于准确识别对象的访问模式——统计信息过期、AWR 报告采样间隔太长、或者开发环境与生产负载差异大,都会导致池分配适得其反。上线前至少观察 3 个业务高峰周期的 v$bh 和 v$segment_statistics 才能下结论。


















