全量刷新适合数据量小、更新频率低且业务能容忍短暂不可用的场景,如几千行配置表每日一次刷新;它不依赖物化视图日志,兼容性最强,但需预留2倍存储空间。

全量刷新适合哪些场景
全量刷新(COMPLETE)本质是重跑整个物化视图定义的查询,丢弃旧数据、重建新结果。它不依赖基表变更日志,兼容性最强,但代价明显。
- 基表没有启用物化视图日志(
MLOG$表),或无法修改基表结构时,只能选全量 - 物化视图 SQL 包含
ROWNUM、RAND()、窗口函数、ORDER BY、UNION或不可重写聚合(如MAX/MIN)时,增量刷新直接失效 - 数据量小(比如几千行配置表)、更新频率极低(每天一次)、且业务能容忍刷新期间短暂不可用或锁表时,全量最省心
- OceanBase 的全量刷新会走“异地刷新”路径(新建隐藏表 + 切换),需要预留 2 倍存储空间,这点容易被忽略
增量刷新(FAST)必须满足的硬条件
增量刷新不是“开关一开就生效”,而是有一串必须全部满足的前置条件,缺一不可。多数失败都卡在第一步。
- 基表必须提前建好物化视图日志:
CREATE MATERIALIZED VIEW LOG ON base_table WITH ROWID, SEQUENCE(col1, col2) INCLUDING NEW VALUES - 物化视图定义中所有 SELECT 列,都得出现在日志的
SEQUENCE列表里;如果用了GROUP BY,所有分组列也必须进日志 - 禁止使用
DISTINCT、HAVING、ROLLUP、内联视图、子查询;聚合仅支持COUNT(*)和SUM,且不能带DISTINCT - Oracle/达梦要求物化视图有唯一键(主键或唯一索引),否则无法定位变更行;PostgreSQL 的
CONCURRENTLY模式也强依赖唯一索引 - 日志类型要匹配:用
ROWID日志时,基表不能做TRUNCATE或在线重组织(ALTER TABLE ... MOVE),否则 ROWID 失效,强制退回到全量
FORCE 刷新不是“智能兜底”,而是有明确 fallback 规则
FORCE 是 Oracle 默认刷新方式,但它不是万能解法——它只按固定逻辑判断,不会自动修复缺失条件。
- 先检查是否满足 FAST 条件:日志存在 + 查询结构合规 + 唯一键可用 → 走增量
- 任一条件不满足 → 直接降级为 COMPLETE,不报错也不提示,容易误以为“自动优化”了
- 在达梦或 OceanBase 中,
REFRESH MATERIALIZED VIEW mv_name(无显式指定)也默认等效于FORCE,行为一致 - 生产环境别依赖
FORCE省事,务必用DBMS_MVIEW.EXPLAIN_MVIEW(Oracle)或EXPLAIN REFRESH(OceanBase)提前验证是否真能走 FAST
刷新策略选择常被低估的隐性成本
真正影响决策的往往不是语法对错,而是资源和一致性之间的拉扯。
- ON COMMIT 刷新看着实时,但每次
INSERT/UPDATE/DELETE都触发刷新,写入延迟可能翻倍——大表或高并发场景慎用 - ON DEMAND 手动刷新最可控,但没人调就永远 stale;配合定时任务(如 Oracle
START WITH ... NEXT或 pg_cron)时,得考虑刷新窗口是否覆盖业务低峰期 - PostgreSQL 的
CONCURRENTLY虽然不阻塞读,但会多占一份临时存储,且刷新时间比非并发模式长 20%~50%,高负载下可能排队 - MySQL 没原生物化视图,靠触发器或事件模拟时,
AFTER INSERT触发器里做UPDATE要小心死锁;用ON DUPLICATE KEY UPDATE增量写入,必须确保物化表有唯一键且覆盖所有维度列

















