物化视图能用FAST REFRESH,但必须同时满足三条硬条件:基表有主键且被完整引用、定义中不含不可重写表达式、存在含SEQUENCE和INCLUDING NEW VALUES的物化视图日志。
物化视图能用 FAST REFRESH 吗?先看这三条硬条件
不能。哪怕 sql 写得再规范、基表数据再干净,只要没满足这三条,fast refresh 会直接报错或退化成 complete 刷新——你根本不会收到明确警告,只发现刷新变慢、日志里悄悄出现 refresh method: complete。
- 基表必须有主键(或启用
ROWID模式且显式声明WITH ROWID),且该主键在物化视图查询中被完整引用 - 物化视图定义里不能含
SYSDATE、USER、子查询、分析函数、外连接(LEFT/RIGHT JOIN)等非可重写表达式 - 必须存在对应基表的物化视图日志(
MATERIALIZED VIEW LOG),且日志包含所有被物化视图引用的列(包括SEQUENCE和INCLUDING NEW VALUES)
建 MVIEW LOG 时最容易漏掉的三个参数
很多人建完日志就以为万事大吉,结果刷新失败。Oracle 对日志字段要求极细,缺一不可:
-
WITH SEQUENCE:必须加。没有它,Oracle 无法判断 DML 顺序,FAST REFRESH直接拒绝执行 -
INCLUDING NEW VALUES:必须加。否则日志只存旧值(OLD VALUES),增量计算时拿不到新行内容,尤其 INSERT 场景直接失效 - 显式列出所有被物化视图 SELECT 的列,例如物化视图查了
id, name, status,日志就得写ON t (id, name, status);只写ON t看似省事,但 Oracle 可能不捕获全部变更
正确示例:
CREATE MATERIALIZED VIEW LOG ON orders WITH SEQUENCE, INCLUDING NEW VALUES (order_id, cust_id, amount, order_date) PURGE EVERY 1 DAY;
FAST REFRESH 失败时最该盯住的两个错误码
别急着改 SQL 或重建日志,先看这两条错误信息,它们直接暴露根因:
-
ORA-12052: cannot fast refresh materialized view string.string:典型“权限/结构”问题。检查基表是否有主键、物化视图是否引用了主键列、日志是否带SEQUENCE和INCLUDING NEW VALUES -
ORA-12004: REFRESH FAST cannot be used for materialized view string.string because it does not have a materialized view log on the master table:不是没建日志,而是日志建在了错误表上(比如基表是sales_detail,却给sales_header建了日志),或日志名拼写与物化视图定义中写的表名大小写不一致(Oracle 默认大写)
刷新方式选 FAST 还是 COMPLETE?关键看变更频率和延迟容忍度
FAST REFRESH 不是万能加速器。它依赖日志维护开销,每次 DML 都要写日志行;而 COMPLETE REFRESH 虽然全量扫表,但无额外日志负担。
- 如果基表每秒更新上百次,且物化视图只读、允许分钟级延迟,
FAST REFRESH日志本身可能成为性能瓶颈 - 如果物化视图仅用于夜间报表,且基表白天写入频繁,反而更适合
COMPLETE REFRESH ON DEMAND+ 定时任务,避开日志写放大 - 混合策略可行:用
DBMS_MVIEW.REFRESH手动指定method => 'F'或'C',而不是依赖ON COMMIT或ON DEMAND的默认行为
真正麻烦的是那种“以为开了 FAST 就一劳永逸”的场景——日志膨胀、刷新卡住、基表主键被删掉却没人通知 DBA。这些细节不在 DDL 里报错,只在运行时咬你一口。










