parallelism参数常无效是因为atomic_refresh=>TRUE时并行被事务捆绑,真正生效需同时设atomic_refresh=>FALSE并启用PARALLEL DML;否则Oracle静默降级为串行,且LOB列、索引缺失或表空间碎片会进一步导致并行失效。

parallelism参数为什么经常没效果
因为 parallelism 在默认的 atomic_refresh => TRUE 下完全不生效——所有并行进程被捆在一个事务里,等最后一起提交,结果就是锁、undo、TX 等待全堆在一起,反而比串行还慢。
真正起作用的前提是:atomic_refresh => FALSE 必须显式传入,且和 parallelism 同时出现。否则 Oracle 会悄悄忽略并行设置,走回串行路径。
- 必须在同一会话中先执行
ALTER SESSION ENABLE PARALLEL DML,再调用DBMS_MVIEW.REFRESH -
parallelism值超过PARALLEL_MAX_SERVERS或 undo 表空间数据文件数,会触发ORA-12853 - 实测稳定值通常为 4–8;设成 16 或更高,收益递减,PGA 抢占严重,影响其他会话
ATOMIC_REFRESH => FALSE 的真实行为和风险
设为 FALSE 后,刷新不再走临时表 + 原子替换,而是直接 TRUNCATE + INSERT /*+ APPEND */,跳过 UNDO 生成,速度可提升 3–5 倍。但这是有代价的:
- 刷新期间物化视图不可用,查询会报
ORA-08103: object does not exist(因 TRUNCATE 瞬间清空) - 若物化视图定义含
GROUP BY、JOIN、聚合函数或子查询,Oracle 会静默退回到atomic_refresh => TRUE,并行失效 - 业务查询需容忍短暂“新旧混合”数据窗口——不是脏读,而是分批提交导致的中间态
怎么确认并行真的跑起来了
不能只看调用语句里写了 parallelism => 8,得验证底层是否真用了并行路径:
- 查
v$sql_plan:如果出现LOAD TABLE CONVENTIONAL,说明INSERT /*+ APPEND */没走通,降级为常规插入,必然慢 - 查
v$active_session_history(别只盯 AWR):快照间隔默认 60 分钟,刷新耗时短于这个就捕不到;重点看enq: TX - row lock contention和direct path write temp - 查
v$session_longops:如果看到大量Parallel Query卡在Sort Segment,大概率是物化视图日志表MLOG$_xxx缺少(snaptime$$, sequence$$)复合索引
LOB 列会让并行刷新彻底失控
哪怕物化视图定义里只带一个 CLOB 或 BLOB,COMPLETE 刷新就会绕过 SQL 层,启用底层 LOB copy 路径,此时 parallelism 行为不可控:
-
parallelism > 1会自动触发 LOB 并行加载,但要求所有 LOB 的CHUNK大小一致(查USER_LOBS.chunk),否则部分 LOB 写入为空 - LOB 数据全量进 UNDO,极易触发
ORA-01555,尤其当atomic_refresh => TRUE时 - 目标表空间若有碎片,直接路径写入频繁等待分配新区,
parallelism越高,等待越明显
LOB 存在时,优先考虑拆出 LOB 列单独维护,或改用 FAST 刷新(前提是日志支持且无 JOIN/GROUP BY)——否则并行只是假象。


















