物化视图刷新CPU飙高主因是默认启用并行,多进程并发扫描大表、JOIN及计算MLOG$差异;高频刷新易引发“刷新雪崩”,需动态降并行度或停job紧急干预,并永久禁用NOPARALLEL及补全索引。
物化视图刷新为什么会让CPU飙到100%
根本原因是 refresh 操作默认可能启用并行(尤其是 fast 或 complete 刷新),多个并行进程同时扫描大表、做 join、计算物化视图日志(mlog$)差异,直接把 cpu 打满。更麻烦的是:如果刷新周期太短(比如每 10 分钟一次),而上次还没刷完,下次就又触发,形成“刷新雪崩”。
- 常见错误现象:
top -H -p <oracle_pid></oracle_pid>看到一堆ora_p00*进程持续占高 CPU;v$session中大量会话状态为ACTIVE,event是direct path read或db file sequential read - 使用场景:物化视图基于大表(如百万级以上)、含多表 join、启用了
ON COMMIT或高频ON DEMAND刷新 - 关键参数影响:
PARALLEL提示、job_queue_processes设置、物化视图定义里的PARALLEL属性、底层表是否建了有效 local 索引
怎么立刻限制正在运行的刷新进程数
不能等刷新完成再处理——得在它还在跑的时候压住并发度。核心是动态修改当前刷新任务的并行度,而不是改系统级参数。
- 先查出正在刷新的物化视图会话:
SELECT s.sid, s.serial#, s.sql_id, p.spid FROM v$session s, v$process p WHERE s.paddr = p.addr AND s.program LIKE '%CJQ%'(CJQ是 job queue 进程,常负责调度刷新) - 对已启动的刷新会话,用
ALTER SESSION临时降级:EXEC DBMS_MVIEW.REFRESH('MV_NAME', 'F', parallelism => 1)—— 注意这不是 DDL,是运行时控制 - 如果刷新由 DBMS_JOB 或 DBMS_SCHEDULER 触发,直接停掉对应 job:
EXEC DBMS_JOB.REMOVE(<job_number>)</job_number>或EXEC DBMS_SCHEDULER.STOP_JOB('<job_name>', force => TRUE)</job_name> - 紧急情况下可 kill 主刷新会话:
ALTER SYSTEM KILL SESSION '<sid>,<serial>' IMMEDIATE</serial></sid>,但要确认不是关键业务依赖的 MV
如何永久禁用物化视图的并行刷新
重建或修改物化视图时,必须显式关闭并行。Oracle 不会因为你没写 PARALLEL 就默认不并行——它可能从表级 PARALLEL 属性继承。
- 重建时加
NOPARALLEL:CREATE MATERIALIZED VIEW mv_xxx NOPARALLEL REFRESH FAST ON DEMAND ... - 已有物化视图,用
ALTER MATERIALIZED VIEW清除并行属性:ALTER MATERIALIZED VIEW mv_xxx NOPARALLEL - 检查底层表是否被设过
PARALLEL:SELECT table_name, degree FROM dba_tables WHERE table_name IN ('T1','T2'),如有,执行ALTER TABLE t1 NOPARALLEL - 确认物化视图日志也无并行:
SELECT log_table, parallel FROM dba_mview_logs,必要时重建日志并指定NOPARALLEL
物化视图刷新慢还和索引有关?
很多人只盯着并行,却忽略一个事实:物化视图刷新本身要频繁访问基表和 MLOG$ 表,如果没有合适索引,就会退化成全表扫描+排序,CPU 自然拉满。
- 必须确保物化视图日志表(如
MLOG$_T1)上有索引:CREATE INDEX idx_mlog_t1_seq ON mlog$_t1 (snaptime$$) NOPARALLEL - 基表上用于快速刷新的字段(如主键、物化视图日志中涉及的列)要有高效索引;如果是分区表,优先建
LOCAL索引 - 别忘了物化视图自身表(
MV_XYZ)也要有索引,尤其当它被下游 SQL 频繁查询时——否则每次查 MV 都会触发额外 CPU 开销 - 验证索引是否生效:
EXPLAIN PLAN FOR EXEC DBMS_MVIEW.REFRESH('MV_XYZ', 'F');,再查PLAN_TABLE,看是否走了索引扫而非全表扫
真正卡住人的地方往往不是“要不要并行”,而是并行开多少、什么时候开、开之前有没有把索引和统计信息理清楚。一个没索引的并行刷新,等于请十个人一起徒手挖山——人越多越乱。


















