真实耗时必须查V$MVREFRESH:刷新前记录DBMS_UTILITY.GET_TIME,刷新后取END_TIME−START_TIME换算秒级耗时;它仅在刷新中或刚结束时可见,需主动轮询,不可依赖滞后更新的DBA_MVIEWS.LAST_REFRESH_DATE。

不能只看 DBA_MVIEWS.LAST_REFRESH_DATE —— 它只存时间点,不存耗时,且更新滞后于实际提交;真实耗时必须从运行时动态视图捕获。
查 V$MVREFRESH 拿单次刷新的精确秒级耗时
这是唯一能拿到“本次刷新执行了多久”的视图,但它只在刷新进行中或刚结束时可见(通常保留几秒到几分钟,取决于系统负载)。关键不是等它“自动出现”,而是主动轮询+计算:
- 刷新前先记下
DBMS_UTILITY.GET_TIME(毫秒级),或用SYSDATE - 立刻执行
SELECT START_TIME, END_TIME FROM V$MVREFRESH WHERE MVIEW_NAME = 'YOUR_MV_NAME' - 若
END_TIME非空,耗时 =(END_TIME - START_TIME) * 24 * 60 * 60(转成秒) - 若
END_TIME为空,说明还在跑;此时别干等,转去看V$SESSION_LONGOPS
常见错误:直接查 DBA_MVIEWS.LAST_REFRESH_DATE 算差值。它可能在刷新成功后延迟数秒甚至更久才更新,尤其在高并发或大事务环境下,结果完全不可信。
用 V$SESSION_LONGOPS 监控正在跑的刷新进度
当刷新卡住、变慢、或你怀疑它没动时,V$SESSION_LONGOPS 是第一响应工具。它反映的是 Oracle 内部对“长时间操作”的实时估算,包括 FAST 和 COMPLETE 刷新:
- 执行
SELECT SID, SERIAL#, OPNAME, TARGET, ROUND(SOFAR/TOTALWORK*100, 2) "%_COMPLETE", SOFAR, TOTALWORK FROM V$SESSION_LONGOPS WHERE OPNAME LIKE 'Refresh%' AND TOTALWORK != 0 AND SOFAR -
OPNAME值为Refresh MV或Refresh Fast MV才是目标 -
%_COMPLETE不是绝对准确,但能判断是否卡死(比如 5 分钟不动在 1%) - 注意:
DBA_MVIEWS.LAST_REFRESH_DATE在这里卡住时纹丝不动,别被它骗了
这个视图不依赖刷新类型,FAST 和 COMPLETE 都会上报;但 ON COMMIT 刷新因在事务内完成,通常太快,很少出现在这里。
确认是否真走 FAST 刷新,而非静默降级
即使 DBMS_MVIEW.REFRESH 返回成功,也可能已悄悄退化为 COMPLETE —— 这种“静默降级”最坑人,因为耗时暴涨却无报错:
- 刷新后立刻查
SELECT FAST_REFRESHABLE FROM DBA_MVIEWS WHERE MVIEW_NAME = 'YOUR_MV_NAME',值必须是YES才算真正支持 FAST - 查日志表消费情况:
SELECT COUNT(*) FROM MLOG$_t WHERE SNAPTIME$$ = TO_DATE('4000-01-01', 'YYYY-MM-DD'),刷新前后对比。差值为 0 → 没走增量;差值非零但耗时高 → 增量逻辑本身慢(比如日志膨胀、基表函数导致无法索引) - 运行
EXEC DBMS_MVIEW.EXPLAIN_MVIEW('YOUR_MV_NAME'),查MVIEW_EXPRESS表里的MSGTXT字段,重点找"REFRESH FAST IS NOT POSSIBLE"或"NO LOG ON BASE TABLE"
ON COMMIT 模式下 FORCE 不会 fallback,但 ON DEMAND 下的 FORCE 就会——这点最容易被忽略。
抓底层 SQL 的执行计划和并行行为
耗时高不一定在 MV 逻辑层,可能卡在生成的刷新 SQL 上。尤其当你传了 parallelism 参数时,得验证它是否真生效:
- 确保
STATISTICS_LEVEL = TYPICAL(BASIC下V$ALL_SQL_PLAN_MONITOR无数据) - 刷新触发后立即查
SELECT KEY, SQL_ID, SQL_EXEC_ID FROM V$ALL_SQL_MONITOR WHERE SQL_TEXT LIKE '%YOUR_MV_NAME%' AND STATUS = 'EXECUTING' - 用拿到的
KEY查SELECT PLAN_OPERATION, DOP, LAST_DEGREE FROM V$ALL_SQL_PLAN_MONITOR WHERE KEY = :key,看到PX COORDINATOR且DOP > 1才算并行启动 - 注意:
parallelism对 FAST 刷新完全无效,只影响 COMPLETE;ON COMMIT 下传该参数会直接报ORA-12054
真正难定位的,是那些“看起来在跑、进度在动、但就是慢”的刷新——往往卡在基表全表扫描、MVIEW$_ 日志表没索引、或 PGA 不足导致大量临时段写入,这些都得靠 V$ALL_SQL_PLAN_MONITOR 和 DBA_HIST_SQL_PLAN 往下挖。


















