物化视图日志冗余主因是建日志时未裁剪字段,应仅包含MV查询所用列及主键列;含冗余字段、缺分区键、未配ROWID/SEQUENCE或INCLUDING NEW VALUES误用均会导致FAST刷新降级、日志膨胀与性能下降。
物化视图日志冗余,90% 是因为建日志时没做字段裁剪,不是 dml 太多
建日志时列列表太宽,把没用的字段全塞进去了
物化视图日志表(MLOG$_xxx)只该存 MV 查询中真正用到的列 + 主键列。如果建日志时写了 WITH ROWID, SEQUENCE (id, name, email, created_at, status, notes),但你的 MV 定义只是 SELECT id, status FROM t,那 name、email 等字段就纯属冗余:
- 每条变更都会多写几 KB 冗余数据,网络传输、日志扫描、Undo 生成全跟着涨
-
notes这类 CLOB 或加密字段无法被日志捕获,会导致 FAST 刷新自动降级为 COMPLETE,触发全量重刷 - Oracle 不校验字段是否真被 MV 使用,建了就记,不删不减
基表是分区表,但日志没包含分区键列
如果基表按 trans_date 范围分区,而日志定义里没把 trans_date 加进 SEQUENCE 列表,Oracle 就没法做分区裁剪。每次 FAST 刷新都得扫全量日志再过滤,哪怕你只改了当天的数据:
- 日志表本身膨胀,
snaptime$$时间戳分散,PURGE_LOG效果打折 - 刷新时大量逻辑读落在 TEMP 表空间,执行计划里出现
TABLE ACCESS FULLonMLOG$_xxx - 验证方式:
SELECT rowids, sequence FROM user_mview_logs WHERE log_table = 'MLOG$_YOUR_TABLE',确认sequence列值为 YES,且字段列表含分区键
用了 INCLUDING NEW VALUES 却没配 ROWID 和 SEQUENCE
这个组合看似完整,实则埋雷:INCLUDING NEW VALUES 要求日志能区分新旧值,但若没开 ROWID,Oracle 就无法定位原记录;没开 SEQUENCE,就无法排序变更顺序。结果就是:
- FAST 刷新失败率升高,频繁降级为 COMPLETE,日志越积越多
- 即使刷新成功,也会多记冗余行——比如一次 UPDATE 可能拆成 DELETE + INSERT 两条日志
- 重建日志必须显式带上:
CREATE MATERIALIZED VIEW LOG ON t WITH ROWID, SEQUENCE (col1, col2) INCLUDING NEW VALUES
日志表长期未被消费,旧快照残留导致“假冗余”
日志表不是按时间自动清理的,而是靠 MV 成功刷新后根据 snaptime$$ 清理。一旦某个 MV 卡住或失败,最早那批日志就一直挂着:
-
SELECT MIN(snaptime$$) FROM MLOG$_xxx返回 2025-01-01,而当前是 2026-06-19 → 明确堆积 -
SELECT COUNT(*) FROM MLOG$_xxx百万级,但SELECT COUNT(*) FROM MLOG$_xxx WHERE snaptime$$ > SYSDATE - 1只有几十行 → 绝大多数是“僵尸数据” - 别直接
TRUNCATE,先跑EXEC DBMS_MVIEW.PURGE_LOG('YOUR_TABLE', 7),它会安全清理过期快照并更新内部状态
真正要砍掉冗余,不是调参数或加索引,而是回到建日志那一刻:只放 MV 真正需要的字段,带齐 ROWID 和 SEQUENCE,且确保分区键在列列表里——其他都是补救措施。


















