Oracle物化视图不会自动启用FAST REFRESH,必须显式创建字段对齐的日志(含SEQUENCE和ROWID或PRIMARY KEY)、基表有主键/唯一约束、MV定义中明确REFRESH FAST ON COMMIT或调用DBMS_MVIEW.REFRESH('F'),且JOIN仅支持INNER及部分LEFT OUTER,否则静默退化为COMPLETE刷新。

Oracle物化视图不会自动启用FAST REFRESH——必须显式创建物化视图日志、满足结构约束、并指定刷新模式,否则即使写了REFRESH FAST,也会静默退化为COMPLETE刷新。
物化视图日志必须手动建,且字段不能少一个
Oracle 绝不会自动为基表创建物化视图日志。漏建、建错表、或字段不全,FAST REFRESH就直接失效,但不会报错,只会悄悄变慢。
-
WITH SEQUENCE和INCLUDING NEW VALUES必须同时存在;缺一不可,否则ORA-12052或刷新退化 - 日志列必须严格覆盖物化视图
SELECT中所有非聚合列(含别名来源列),例如物化视图查了empno, UPPER(ename) AS name,日志就得包含empno, ename,不能只写*或省略ename - 如果基表用
PRIMARY KEY做唯一标识,日志必须带WITH PRIMARY KEY;若用ROWID,则必须带WITH ROWID,二者不可混用或遗漏 - 示例正确语句:
CREATE MATERIALIZED VIEW LOG ON emp WITH PRIMARY KEY, SEQUENCE (empno, ename, job, sal) INCLUDING NEW VALUES;
基表主键和物化视图定义必须对齐
快速刷新依赖可确定的行粒度变更追踪,所以主键不是“有就行”,而是要被物化视图显式引用、且不能被隐藏或转换。
- 基表必须有
PRIMARY KEY或UNIQUE NOT NULL约束,且该约束列必须出现在物化视图的SELECT列表中(不能只在GROUP BY里) - 禁止在物化视图查询中使用
SYSDATE、USER、子查询、分析函数(如ROW_NUMBER())、LEFT JOIN(仅支持INNER JOIN和部分LEFT OUTER JOIN) - 聚合类物化视图必须包含
COUNT(*),否则无法判断删除行——这是很多ORA-12004的隐藏原因 - 错误写法:
SELECT deptno, SUM(sal) FROM emp GROUP BY deptno→ 缺COUNT(*),FAST失败 - 正确写法:
SELECT deptno, COUNT(*), SUM(sal) FROM emp GROUP BY deptno
REFRESH FAST ON COMMIT 和 ON DEMAND 的实际差异
ON COMMIT看似“全自动”,但代价是每次事务提交都触发一致性检查和日志扫描,高并发下会明显拖慢基表DML;ON DEMAND更可控,但需配合调度主动调用。
-
ON COMMIT要求所有涉及基表都有日志,且整个事务链路不能跨数据库链接(DB Link),否则直接禁用FAST -
ON DEMAND下必须用DBMS_MVIEW.REFRESH('mv_name', 'F')显式触发;传'F'才走快速路径,传'?或不指定类型会走FORCE逻辑,可能退化 - 自动调度推荐用
DBMS_SCHEDULER而非老旧的DBMS_JOB,避免时间漂移和权限问题 - 刷新前建议先运行
DBMS_MVIEW.EXPLAIN_MVIEW检查是否真能FAST,比盲刷更可靠
最容易被忽略的点是:物化视图日志的列清单必须和物化视图实际引用的列完全一致——不是“基表有哪些列”,而是“这个MV的SQL里真正读了哪些原始列”。哪怕只差一个大小写或别名映射,FAST就会失效,而Oracle通常只在日志里记一句refresh method: complete,不抛异常也不警告。


















