物化视图刷新慢主因是调度器瓶颈而非sql性能;需检查dba_mviews/dba_refresh状态、作业是否broken、job_queue_processes参数,并升级至dbms_scheduler绑定资源组,配合parallelism与atomic_refresh调优。
物化视图刷新慢,先查 dba_mviews 和 dba_refresh 看是否卡在作业队列
oracle 物化视图刷新延迟高,80% 以上情况不是 sql 本身慢,而是刷新作业被调度器“压着没跑”。关键看两点:last_refresh_date 和 staleness 是否长期不更新;refresh_method 是 fast 还是 complete(后者更容易排队)。如果 dba_refresh 里对应刷新组的 name 显示 delayed 或长时间无新作业记录,说明调度层已成瓶颈。
实操建议:
- 运行
SELECT NAME, NEXT_DATE, BROKEN, WHAT FROM DBA_JOBS WHERE WHAT LIKE '%dbms_mview.refresh%',确认刷新作业是否被设为BROKEN = TRUE或NEXT_DATE滞后数小时 - 检查
job_queue_processes参数值(SHOW PARAMETER job_queue_processes),低于 10 时高并发刷新必然排队——尤其当多个 MV 共享同一刷新组 - 若使用 Oracle 12c+,优先改用
DBMS_SCHEDULER替代DBMS_JOB,后者已废弃且无法设置资源计划绑定
用 DBMS_SCHEDULER 替换旧作业并绑定资源消费者组
DBMS_JOB 的作业没有优先级、无法限 CPU、也不能按业务重要性分组;而 DBMS_SCHEDULER 支持直接绑定 RESOURCE_CONSUMER_GROUP,这才是降低延迟的核心手段。
实操建议:
- 停用原
DBMS_JOB刷新作业:执行DBMS_JOB.REMOVE(<job_number>)</job_number>,再清空USER_JOBS中残留项 - 创建专用消费者组(如
MV_HIGH_PRIORITY):用DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP,并分配更高 CPU 比例(例如 40%,默认OTHER_GROUPS只有 5%) - 新建 scheduler 作业时显式指定:
attribute => 'RESOURCE_CONSUMER_GROUP', value => 'MV_HIGH_PRIORITY';同时设置START_DATE精确到秒,避免默认延迟 - 避免用
REPEAT_INTERVAL => 'FREQ=DAILY'这类模糊表达——改用'FREQ=SECONDLY; INTERVAL=300'(5 分钟)并配合MAX_RUNS => 1+ 手动触发链,更可控
DBMS_MVIEW.REFRESH 调用时加 parallelism 和 atomic_refresh 参数
即使调度及时,单次刷新慢也会拖累整体延迟。特别是 COMPLETE 刷新,默认串行且重建整个表,容易卡住。两个参数最关键:parallelism 控制并行度,atomic_refresh 决定是否走 TRUNCATE+INSERT(快但锁表)还是 MERGE(慢但低影响)。
实操建议:
- 对非核心业务 MV,强制并行:
DBMS_MVIEW.REFRESH('MV_SALES_DAILY', method => 'C', parallelism => 4);注意parallelism值不能超过PARALLEL_MAX_SERVERS当前可用数 - 若允许短时锁表(如夜间维护窗口),设
atomic_refresh => FALSE:跳过日志、直接 truncate,速度可提升 3–5 倍;否则保持TRUE(默认),但需确保 MV 日志(MLOG$)未膨胀——查DBA_MVIEW_LOGS的LOG_TABLE行数是否超千万 - 不要在 PL/SQL 块中裸写
DBMS_MVIEW.REFRESH,务必包在EXCEPTION块里捕获ORA-12008(刷新路径错误)和ORA-04021(对象编译锁等待)
监控刷新延迟不能只盯 LAST_REFRESH_DATE
LAST_REFRESH_DATE 只反映“完成时间”,但真正影响下游应用的是“数据就绪时刻”——中间可能经历日志应用延迟、主从同步 lag、甚至调度器重试间隔。很多团队调优半天,结果发现延迟源头在备库没跟上。
实操建议:
- 在刷新作业执行后立刻查
SELECT MIN(SEQUENCE#), MAX(SEQUENCE#) FROM V$ARCHIVED_LOG WHERE FIRST_TIME > SYSDATE - 1/24,比对主库归档生成序列和备库接收序列差值 - 对基于主从复制的 MV(如 GoldenGate 同步源表),在刷新前加
DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER记录 SCN,刷新后查V$ARCHIVE_DEST_STATUS的APPLIED_SCN是否追平 - 禁用
DBMS_MVIEW.REFRESH的自动重试(rollback_seg默认开启):显式传rollback_seg => NULL,否则失败后等 60 秒再试,会掩盖真实耗时点
真正卡住的地方,往往不在 MV 自身 SQL,而在调度器资源配额、底层归档传输、或消费者组权重配置错了一位小数。调参前先抓 5 分钟 AWR 报告,重点看 resmgr:cpu quantum 和 DFS lock handle 等待事件。











