可以,但必须显式声明;oracle 19c中物化视图不继承基表或表空间的inmemory属性,需在create或alter语句中显式指定inmemory子句,否则不会加载至im列存储区。

物化视图能否直接启用INMEMORY?
可以,但必须显式声明。Oracle 19c 中,MATERIALIZED VIEW 本身不继承表或表空间的 INMEMORY 属性,即使基表已开启 In-Memory,物化视图也不会自动加载进内存列存储区。你得在创建时或后续通过 ALTER MATERIALIZED VIEW ... INMEMORY 显式启用。
常见错误现象:SELECT * FROM V$IM_SEGMENTS 查不到物化视图名,或 V$IM_USER_SEGMENTS 中 POPULATE_STATUS 长期为 NOT POPULATED ——不是 In-Memory 没生效,而是根本没配。
注意两点:
-
INMEMORY只对物化视图的物理存储结构生效,不影响其刷新逻辑或查询重写行为 - 启用后,物化视图数据会以列式格式加载进 IM Column Store(位于 SGA 的共享池内),但其索引、日志、统计信息仍走传统路径
分区物化视图的INMEMORY配置要点
分区物化视图支持细粒度 In-Memory 控制,但语法和行为有约束:
- 必须在创建时指定
INMEMORY,或对已存在 MV 执行 ALTER MATERIALIZED VIEW mv_name INMEMORY;不能只对某个分区单独启用(不像普通分区表支持 ALTER TABLE ... MODIFY PARTITION p1 INMEMORY)
- 若 MV 基于分区表构建且自身也做了
PARTITION BY RANGE,整个 MV 作为单一 IM 对象加载,不按分区切片加载
- 压缩级别可设:例如
INMEMORY (PRIORITY HIGH, COMPRESSION FOR QUERY LOW),但注意 FOR QUERY 压缩比 FOR CAPACITY 更适合聚合类报表查询
- 不要依赖
INMEMORY_CLAUSE 自动推导:即使 MV 定义里用了 GROUP BY time_id,Oracle 也不会自动把 time_id 列设为高优先级,必须手动指定列级策略,如 INMEMORY (time_id, region) PRIORITY CRITICAL
INMEMORY + 查询重写的实际效果如何?
二者能共存,但不叠加加速:In-Memory 加速的是“从物化视图读数据”的环节,而查询重写(QUERY REWRITE)解决的是“让查询命中物化视图”这个前提。如果重写失败,哪怕 MV 已全量驻留内存,查询仍会回退到基表。
INMEMORY,或对已存在 MV 执行 ALTER MATERIALIZED VIEW mv_name INMEMORY;不能只对某个分区单独启用(不像普通分区表支持 ALTER TABLE ... MODIFY PARTITION p1 INMEMORY)PARTITION BY RANGE,整个 MV 作为单一 IM 对象加载,不按分区切片加载INMEMORY (PRIORITY HIGH, COMPRESSION FOR QUERY LOW),但注意 FOR QUERY 压缩比 FOR CAPACITY 更适合聚合类报表查询INMEMORY_CLAUSE 自动推导:即使 MV 定义里用了 GROUP BY time_id,Oracle 也不会自动把 time_id 列设为高优先级,必须手动指定列级策略,如 INMEMORY (time_id, region) PRIORITY CRITICAL
QUERY REWRITE)解决的是“让查询命中物化视图”这个前提。如果重写失败,哪怕 MV 已全量驻留内存,查询仍会回退到基表。
容易被忽略的关键点:
-
V$IM_SEGMENTS显示 MV 已加载 ≠ 查询一定走 MV:先确认DBMS_MVIEW.EXPLAIN_REWRITE返回TEXT_MATCH或GENERAL - 启用
INMEMORY后,MV 的STATISTICS仍需手动收集(DBMS_STATS.GATHER_TABLE_STATS),否则优化器可能因误估成本而放弃重写 - 如果 MV 含大量 NULL 值列,
INMEMORY默认压缩效率低,建议显式加NO INMEMORY (col_with_many_nulls)排除干扰列
为什么刷新变慢了?INMEMORY 和 FAST 刷新冲突吗?
不直接冲突,但有隐性开销:
- FAST 刷新本身不触发 IM 区域重加载,但每次增量变更(INSERT/UPDATE/DELETE)后,Oracle 会异步标记对应 IM segment 为“需重新 populate”,导致后续首次查询时出现短暂延迟
- COMPLETE 刷新会清空并重建 MV 物理段,此时 IM 区域需重新加载全量数据,若 MV 较大(比如上百 GB),populate 过程可能持续数分钟,期间查询性能回落
- 并行刷新(
atomic_refresh => FALSE)与 INMEMORY 兼容,但要注意:并行插入新数据后,IM population 是单线程异步进行的,无法并行加载
atomic_refresh => FALSE)与 INMEMORY 兼容,但要注意:并行插入新数据后,IM population 是单线程异步进行的,无法并行加载真正影响体验的往往是内存分配节奏:INMEMORY_SIZE 不足时,MV 可能被部分 evict;INMEMORY_FORCE 设为 DEFAULT 时,小查询可能根本不会触发 populate;
最稳妥的做法是:刷新完成后,立刻执行 DBMS_INMEMORY.POPULATE 显式加载,并监控 V$IM_SEGMENTS.POPULATE_STATUS 确认完成。











