dbms_mview.refresh卡在日志表全扫上,根本原因是mlog$_xxx表高水位线(hwm)悬空,导致oracle仍扫描大量空块;需先验证空间占用,再通过enable row movement + shrink space compact收缩hwm,并检查fast刷新前提、并行参数配对使用(atomic_refresh=>false)、统计信息更新及explain_mview根因分析。
dbms_mview.refresh卡在日志表全扫上
不是sql慢,而是mlog$_xxx表高水位线(hwm)悬空,哪怕select count(*) from mlog$_your_table返回0,oracle仍从hwm开始全表扫描。常见现象:刷新耗时几分钟,但日志行数极少。
- 先确认真实空间占用:
SELECT bytes/1024/1024 AS mb FROM dba_segments WHERE segment_name = 'MLOG$_YOUR_TABLE'—— 若远大于行数,说明HWM悬空 - 收缩日志表:
ALTER TABLE MLOG$_YOUR_TABLE ENABLE ROW MOVEMENT,再ALTER TABLE MLOG$_YOUR_TABLE SHRINK SPACE COMPACT - 避免无效DML:比如
UPDATE t SET name = UPPER(name)会为每行记日志;应加WHERE name != UPPER(name) - 检查是否有其他MV共享该日志但长期未刷新——孤立日志必须清理:
DROP MATERIALIZED VIEW LOG ON your_table后重建
parallelism参数没生效,其实是atomic_refresh锁死了
设了parallelism => 4却还是单线程跑,大概率是atomic_refresh还在默认TRUE。这个参数不关,所有并行进程都挤在一个事务里等提交,锁、undo、TX等待全来了。
- 必须配对使用:
DBMS_MVIEW.REFRESH('mv_name', method => 'F', parallelism => 4, atomic_refresh => FALSE) -
atomic_refresh => FALSE后,刷新变成分批提交(如每5万行commit一次),锁粒度变小,但MV在刷新中可能短暂返回新旧混合数据 - 切忌同时设
refresh_after_errors => TRUE:出错跳过批次后,已提交部分无法回滚,状态不可逆 - 验证是否真并行:
SELECT * FROM v$PX_SESSION,刷新期间应看到多个PX进程;若只看到1个,说明parallelism被忽略或降级
你以为在跑FAST刷新,其实后台悄悄切成了COMPLETE
定义写了REFRESH FAST,调用也传了'F',但实际执行的是全量重建——Oracle不报错,只默默退化。耗时突增或监控异常才是信号。
- 执行前必查:
SELECT LOG_TABLE, ROWIDS, PRIMARY_KEY, SEQUENCE, INCLUDING_NEW_VALUES FROM USER_MVIEW_LOGS WHERE MASTER = 'YOUR_TABLE'—— 五项都要YES才真正支持FAST - 用
DBMS_MVIEW.EXPLAIN_MVIEW('MV_NAME')看MSGTXT字段,出现"REFRESH FAST IS NOT POSSIBLE"或"NO LOG ON BASE TABLE"就直接定位根因 - 即使EXPLAIN说“可快刷”,但刷新仍慢,问题一定出在日志积压、索引缺失或锁等待上,不是SQL本身
- 基表有LOB列(哪怕只是定义里带一个
CLOB),FAST刷新也可能被跳过,直接走COMPLETE路径
刷新后查询变慢,其实是统计信息没更新
物化视图刷新只改数据,不触发统计信息收集。优化器仍按旧数据量和分布做计划,结果该走索引的走了全表扫描,该分区裁剪的扫了全部分区。
- 查
DBA_TAB_STATISTICS中物化视图记录的LAST_ANALYZED时间,是否晚于最近一次刷新时间 - 立即执行:
DBMS_STATS.GATHER_TABLE_STATS('SCHEMA_NAME', 'MV_NAME', cascade => TRUE, estimate_percent => 10, method_opt => 'FOR COLUMNS SIZE 254 KEY_COL, TIME_COL') - 若建在预建表上,统计必须收集到物理表名,不是物化视图名
-
DBA_MVIEWS.STALENESS = 'FRESH'只表示数据同步,不代表统计可用;统计陈旧时,查询重写也可能被跳过
复杂点在于:这些因素常叠加出现——日志膨胀 + atomic_refresh=TRUE + 统计陈旧,三者一起作用时,单点优化几乎无效。最容易被忽略的是EXPLAIN_MVIEW输出和dba_segments空间检查,这两步不做,后面所有调参都是盲调。











