物化视图不支持在线重定义,DBMS_REDEFINITION仅适用于基表;需先重定义基表并重建MV日志,再重建物化视图以启用PCT和查询重写。

不能直接对物化视图(MATERIALIZED VIEW)执行在线重定义 —— DBMS_REDEFINITION 只支持普通表(TABLE),不支持物化视图本身。如果你看到“对物化视图做在线重定义分区”,实际操作对象一定是该物化视图的**基表**,而非物化视图对象。
为什么不能对物化视图调用 START_REDEF_TABLE
Oracle 明确限制 DBMS_REDEFINITION 的目标对象类型为堆表或索引组织表(IOT),不包括物化视图、视图、临时表等。尝试对物化视图名传入 START_REDEF_TABLE 会立即报错:
ORA-12089: 不能联机重新定义无主键的表 "SCHEMA"."MV_NAME"
这个错误看似在说“没主键”,实则是底层校验发现对象类型非法,提前终止;即使物化视图有主键(它根本不能定义主键),也会卡在这一步。
- 物化视图是只读查询结果的快照,其结构由
SELECT语句决定,无法像表一样增删列或改分区策略 - 分区只能作用于存储数据的物理对象(即基表),物化视图的“分区”行为完全依赖基表是否分区 + 查询重写是否启用
- 若你真正想优化的是物化视图刷新性能,应优先检查基表分区设计、MV 日志、PCT(Partition Change Tracking)是否启用
正确路径:重定义基表,再重建物化视图
要让物化视图受益于分区,必须先确保其依赖的**基表已分区**,且重定义过程不破坏物化视图依赖链。典型步骤如下:
- 确认物化视图的基表(查
DBA_MVIEWS的QUERY字段或DBA_DEPENDENCIES) - 对该基表执行标准在线重定义(如转为
PARTITION BY RANGE)—— 要求基表有主键、足够空间、用户有EXECUTE_CATALOG_ROLE和ALTER ANY TABLE等权限 - 重定义完成后,
DROP原物化视图,用相同SELECT语句 +ON PREBUILT TABLE(如果原 MV 基于已存在表)或全新CREATE MATERIALIZED VIEW重建 - 重建时显式启用 PCT:
ENABLE QUERY REWRITE, ENABLE ON QUERY COMPUTATION(11g+ 支持)
注意:重定义期间基表仍可 DML,但物化视图刷新会失败或延迟,需协调业务窗口。
COPY_TABLE_DEPENDENTS 对物化视图日志的特殊处理
如果基表上有物化视图日志(MLOG$ 表),COPY_TABLE_DEPENDENTS 默认不会复制它 —— 这是关键盲点。重定义后基表的 MV 日志会失效,导致后续快速刷新失败。
- 必须手动在重定义后的基表上重建 MV 日志:
CREATE MATERIALIZED VIEW LOG ON base_table WITH ROWID, SEQUENCE(col1,col2) INCLUDING NEW VALUES; - 或者,在调用
COPY_TABLE_DEPENDENTS时显式启用日志复制(11gR2+ 支持):dbms_redefinition.copy_table_dependents(..., copy_mv_log => TRUE); - 验证日志是否就位:
SELECT * FROM user_mview_logs WHERE master = 'BASE_TABLE';
漏掉这步,物化视图将退化为完全刷新,大表场景下刷新耗时可能从秒级升至小时级。
分区键与物化视图查询重写的匹配要点
即使基表成功分区,物化视图也不自动获得分区裁剪能力。必须满足:
- 物化视图定义中的
SELECT必须包含基表的分区键列(如WHERE sale_date BETWEEN ...) - 创建 MV 时指定
ENABLE QUERY REWRITE,且数据库参数QUERY_REWRITE_ENABLED=TRUE - 基表分区方式需与 MV 查询谓词兼容:范围分区对应范围谓词,列表分区对应等值谓词
- 避免在 MV 查询中对分区键列使用函数(如
TO_CHAR(sale_date)),否则 PCT 失效
最易忽略的是:重定义后基表的分区键列名/类型未变,但物化视图的 SELECT 若用了别名或隐式转换,可能导致查询重写引擎无法识别分区裁剪机会。


















