备库启用in-memory必须手动确认并配置三处关键参数:inmemory_size非零、inmemory_adg_enabled=true、rac环境下parallel_degree_policy=auto且parallel_force_local=false,否则alter table...inmemory在备库无效。
备库启用 in-memory 不是“主库开了,备库就自动跟上”,必须手动确认并配置三处关键参数,否则 alter table ... inmemory 在备库上只是个无效声明。
查备库是否真启用了 In-Memory
很多人以为主库开了,备库就生效了,其实备库的 inmemory_size 默认是 0 —— 这意味着整个 IM 列存储区域压根没分配。直接执行:
SHOW PARAMETER inmemory_size
如果返回值是 0,说明备库连内存池都没建,后续所有操作都无效。
-
inmemory_adg_enabled默认为TRUE,但它只表示“允许启用”,不是“已启用” - RAC 环境下还要额外检查:
parallel_degree_policy = AUTO且parallel_force_local = FALSE,否则即使数据进了内存,也用不上并行扫描 - 别依赖
v$im_segments查表状态——如果inmemory_size=0,这个视图甚至可能为空或报错
给备库分配 In-Memory 内存不能直接改 SPFILE
ADG 备库的 SPFILE 通常由主库统一管理,你在备库上执行 ALTER SYSTEM SET inmemory_size=8G SCOPE=SPFILE,重启后大概率被主库后续参数同步覆盖。
- 推荐方式:在 PDB 级别设置,比如在备库的
ORCLPDB1中执行ALTER SYSTEM SET inmemory_size=8G SCOPE=SPFILE,再单独重启该 PDB(不影响 CDB 和其他 PDB) - 非 CDB 或需全局生效时,必须在主库修改 SPFILE,并确保
LOG_ARCHIVE_CONFIG和 DG Broker 配置完整,否则参数不会推送到备库 - 大小建议从
4G起步,上限不超过物理内存的 25%;设太大容易触发ORA-04030,尤其当备库同时跑 MRP 进程和大量只读查询时
表声明 INMEMORY ≠ 数据已进内存
ALTER TABLE sales INMEMORY 只是注册加载策略,备库不会回放主库的 IM 加载动作,也不会自动预热。
- 首次查询会触发异步加载,但第一条 SQL 必然慢——要从磁盘读块、解压、转成列格式,这是设计行为,不是 bug
- 生产环境建议主动预热:
EXEC DBMS_INMEMORY.POPULATE('SALES'),注意该过程吃 CPU 和 IM 内存,避开业务高峰 - 验证是否真正落地:
SELECT segment_name, populate_status FROM v$im_segments WHERE segment_name = 'SALES',状态必须是COMPLETED才算成功 - 压缩策略影响显著:对分析型大表,
MEMCOMPRESS FOR CAPACITY HIGH比默认QUERY LOW省约 40% 内存,但 CPU 解压开销会上升
外部表也能进备库 In-Memory,但有隐含前提
Oracle 19c 在 Exadata 上支持外部表自动进 IM,但普通环境仍需手动触发,且有个关键限制:
- 必须先将
QUERY_REWRITE_INTEGRITY设为stale_tolerated,否则查询会报错或绕过 IM 路径 - 创建外部表时要显式加
INMEMORY MEMCOMPRESS FOR CAPACITY HIGH,否则即使参数开了,也不进内存 - 非 Exadata 环境下,
DBMS_INMEMORY.POPULATE是唯一可靠方式;Exadata 上虽可自动加载,但仍建议查v$im_segments确认状态
最容易被忽略的是 RAC 下的并行策略和 PDB 级参数隔离——这两个点不满足,哪怕内存配了、表也声明了,查询计划里照样看不到 TABLE ACCESS INMEMORY FULL。











