多表JOIN分区物化视图FAST刷新必须满足四条硬性条件:所有基表须建含ROWID、SEQUENCE及所有JOIN/WHERE/GROUP BY列的物化视图日志;禁用外连接;分区表日志须建在整表且含INCLUDING NEW VALUES;查询中禁用ROWNUM、DISTINCT、未配COUNT(*)的聚合等。

多表JOIN分区物化视图的FAST刷新必须满足哪些硬性条件?
Oracle 19c 不允许“碰运气”式建多表 JOIN 的快速刷新物化视图。只要任意一条不满足,REFRESH FAST 就会静默退化为 COMPLETE,甚至直接报 ORA-12054。关键约束有四条:
- 所有参与 JOIN 的基表(不止主表)都必须创建物化视图日志,且日志必须含
WITH ROWID, SEQUENCE,并显式包含所有 JOIN 列、WHERE 条件列、GROUP BY 列(如有聚合) - 若物化视图定义含外连接(
LEFT JOIN等),FAST 刷新完全不可用——必须拆成UNION ALL + INNER JOIN / NOT EXISTS结构 - 分区表作为基表时,日志必须建在整张表上(不能只建在某个分区),且需加
INCLUDING NEW VALUES,否则ON COMMIT场景下 UPDATE 无法捕获旧值 - 物化视图查询中不能出现
ROWNUM、DISTINCT、子查询(除非等价转写为 JOIN)、聚合函数未配COUNT(*)(如只用SUM(x)不行)
为什么分区表 JOIN 后总卡在 MLOG$ 扫描阶段?
不是 SQL 写得慢,是日志扫描逻辑本身在“硬扫”。当多个分区表同时更新,MLOG$_t1、MLOG$_t2 等日志表可能各自积累数十万行,而 Oracle 快速刷新引擎默认对每个日志表做全表扫描 + ORDER BY sequence$$, snaptime$$ 去重合并——一旦缺少索引或统计信息过期,就会触发磁盘排序和大量 BUFFER_GETS。
- 必须为每个日志表建复合索引:
CREATE INDEX idx_mlog_t1_seq ON mlog$_t1 (snaptime$$, sequence$$) - 执行
DBMS_STATS.GATHER_TABLE_STATS(user, 'MLOG$_T1')更新统计信息,避免优化器误选嵌套循环 - 定期清理已消费日志:
DBMS_MVIEW.PURGE_LOG('T1', 1)(保留 1 天),防止日志膨胀拖垮后续刷新 - 若某次刷新后发现
V$SESSION_WAIT中长时间等待direct path read temp,基本可断定是排序区 PGA 不足,需调大PGA_AGGREGATE_TARGET
如何让并行机制真正作用于多表 JOIN 的 FAST 刷新?
DBMS_MVIEW.REFRESH(parallelism => 8) 对 FAST 刷新完全无效——这是最常被误解的一点。Oracle 内部对快速刷新采用单线程 delta 合并逻辑,无论你传 PARALLELISM => 16 还是 999,执行计划里永远看不到 PX COORDINATOR 或 PX SEND 操作符。
- 并行只在
COMPLETE刷新时生效:此时整个 AS 子查询被重跑,parallelism参数会转为 SQL 层的/*+ PARALLEL(8) */Hint -
FORCE模式下,若因日志缺失/损坏导致退化为COMPLETE,并行才起作用;若仍走FAST,参数被静默丢弃 - 验证是否真并行:刷新触发后立即查
V$ALL_SQL_PLAN_MONITOR,过滤sql_text LIKE '%your_mv_name%',再查plan_operation是否含PX类操作、dop > 1 - 并行度受
PARALLEL_MAX_SERVERS和当前空闲 server 数限制,超限会自动降级为串行,不报错
ATOMIC_REFRESH=FALSE 在分区 JOIN 场景下要不要开?
要开,但仅限大分区批量刷新且能接受短暂空表风险的场景。它不改变刷新逻辑,只改变事务包装方式:跳过临时表 + 原子事务,改为直接 TRUNCATE + INSERT /*+ APPEND */。
- 优势明显:大幅降低 UNDO/REDO 生成量,避免长事务锁表,对 TB 级分区尤其有效
- 风险具体:刷新中途失败(如空间不足、权限丢失),物化视图将处于空表状态,下游查询立即报
ORA-01403: no data found - 不能用于
ON COMMIT模式——该模式强制ATOMIC_REFRESH => TRUE,设为 FALSE 会报错 - 若必须兼顾安全与性能,可用分步策略:先用
ATOMIC_REFRESH => FALSE刷最新分区,再用ATOMIC_REFRESH => TRUE补刷历史小分区
多表 JOIN 分区物化视图的快速刷新,本质是把“语义确定性”和“物理可追踪性”强行对齐的过程。最容易被忽略的不是语法,而是日志字段是否覆盖所有 JOIN 路径、INCLUDING NEW VALUES 是否漏加、以及误以为 parallelism 能加速 FAST 刷新——这三点踩中任一,就等于白配置。











