物化视图本身不支持快速刷新,必须基表有主键或已建含PRIMARY KEY/ROWID、SEQUENCE、INCLUDING NEW VALUES的物化视图日志,且查询不能含外连接、聚合、子查询等禁用结构。

物化视图本身不支持快速刷新?先看基表有没有主键或日志
Oracle 19c 中,REFRESH FAST 不是“建了就能用”的功能,它依赖基表是否具备增量变更捕获能力。没有主键、也没建 MATERIALIZED VIEW LOG 的表,连 CREATE MATERIALIZED VIEW ... REFRESH FAST 都会直接报错——最常见的是 ORA-12014(表不含主键约束)或 ORA-12052(无法对表执行快速刷新)。别指望 REFRESH FORCE 在这里兜底:它在 ON COMMIT 或 ON DEMAND 场景下,仍强制要求 FAST 可行;不可行就失败,不会退化成 COMPLETE。
- 优先检查基表是否有
PRIMARY KEY:有就用WITH PRIMARY KEY,最稳定 - 没主键?只能退用
WITH ROWID,但要求物化视图查询中显式包含table_name.ROWID,且不能含外连接、聚合、子查询等禁用结构 - 哪怕只少一个字段、漏一个参数,日志就“形同虚设”——后续所有
REFRESH FAST都会静默降级为 COMPLETE
建物化视图日志必须带三个关键参数:SEQUENCE、INCLUDING NEW VALUES、PRIMARY KEY 或 ROWID
CREATE MATERIALIZED VIEW LOG ON table_name 这条语句如果缺参数,等于白建。Oracle 不会警告,但日志表(如 MLOG$_sales)里根本不会生成 SEQUENCE$$、OLD_NEW$$ 等关键字段,导致刷新时找不到增量依据。
- 必须二选一:
WITH PRIMARY KEY或WITH ROWID(推荐前者) -
SEQUENCE(id, name, deptno)必须包含该表在物化视图中**所有被引用的列**:不只是SELECT列,还包括JOIN条件列、WHERE中过滤列、GROUP BY列 -
INCLUDING NEW VALUES不可省略:否则 UPDATE 和 DELETE 无法正确识别新旧值,聚合类 MV(如COUNT(*))必失效 - 多张 MV 共用一张基表?
SEQUENCE()和INCLUDING NEW VALUES必须覆盖所有 MV 的字段并集,不能按单个 MV 定义来写
物化视图定义里不能出现外连接、聚合、子查询等禁用结构
即使日志建得再全,只要物化视图 SQL 含 LEFT JOIN、GROUP BY、SUM()、ROW_NUMBER()、SYSDATE 或非确定性函数,REFRESH FAST 就一定失败——Oracle 在 CREATE 阶段就会拒绝,报 ORA-12054 或 ORA-32313。这不是配置问题,是语义限制:外连接结果无法被增量推导,聚合值无法从单行变更反向计算。
- LEFT JOIN 替代方案:用
UNION ALL拆成 INNER JOIN + NOT EXISTS 两部分,每部分都满足 FAST 条件 - 聚合类需求(如统计销量):必须配合
MATERIALIZED VIEW LOG WITH PRIMARY KEY ... SEQUENCE(...),且 SELECT 中必须包含基表主键和所有 GROUP BY 列 - 查询里用了
TO_CHAR(created_date, 'YYYY-MM')?不行。日期格式化是非确定性的,FAST 不认 - 字段别名、
DISTINCT、ORDER BY、HAVING—— 全部禁止出现在 FAST MV 定义中
验证是否真走 FAST 刷新:别信“创建成功”,要看元数据和日志内容
建完物化视图后执行 SELECT * FROM user_mviews WHERE mview_name = 'YOUR_MV',只看 REFRESH_METHOD 是 FAST 还不够。真正关键的是 STALENESS 和日志状态——很多“看起来能刷”的 MV,第一次刷新就退化 COMPLETE,只是你没察觉。
- 查日志是否活:运行
SELECT * FROM MLOG$_your_table WHERE SNAPTIME$$ = TO_DATE('4000-01-01', 'YYYY-MM-DD'),返回非空说明日志已捕获变更;返回 0 行,说明 DML 没触发日志(比如用了TRUNCATE)或日志无效 - 查日志结构:
DESC MLOG$_your_table,确认存在SEQUENCE$$、SNAPTIME$$、OLD_NEW$$字段 - 刷新后立刻查
user_mviews.staleness:如果是STALE,说明 FAST 链已断,下次刷新大概率 fallback 到 COMPLETE - 基表被
ALTER TABLE ... DROP PRIMARY KEY或TRUNCATE过?日志立即失效,FAST 刷新永久不可用,必须重建日志甚至重定义 MV
真正卡住人的地方不在语法,而在日志和基表状态的隐式耦合——建完日志不做一次真实 DML(INSERT/UPDATE/DELETE),日志就是死的;建完 MV 不检查 staleness,你就永远不知道它其实在“假装 FAST”。











