物化视图压缩必须在create时指定,alter不支持;空间未释放主因是日志表mlog$_xxx未清理或基表未压缩;安全清理需先确认无mv引用日志,再drop日志并更新统计信息与索引。

物化视图本身不能“清理”,只能重建或压缩;空间没降下来,90%是因为日志表(MLOG$_xxx)没动,或者底层表没真正压缩。
为什么 ALTER MATERIALIZED VIEW COMPRESS 不生效
Oracle 明确不支持用 ALTER MATERIALIZED VIEW 添加压缩。执行会直接报 ORA-00922: missing or invalid option。物化视图的压缩属性必须在 CREATE 时声明,建完就固定了。
唯一可行路径是:
- 确认刷新策略是否允许中断:如果是
ON COMMIT类型,重建期间基表 DML 会被阻塞 - 查真实表名:
SELECT mview_name, table_name FROM user_mviews WHERE mview_name = 'MV_SALES_DAILY',避免误删 - 用
DROP MATERIALIZED VIEW mv_sales_daily+ 重建语句加COMPRESS FOR OLTP(企业版)或COMPRESS BASIC(标准版) - 若不想停服务,可退而求其次:
ALTER TABLE mv_sales_daily COMPRESS FOR OLTP,但需注意锁和权限
日志表 MLOG$_xxx 占空间最多,但不能 TRUNCATE 或 DROP TABLE
直接 TRUNCATE TABLE sys.mlog$_sales 看似释放空间,实则埋雷:高水位线(HWM)下降,但段头块残留元信息,后续插入可能触发异常扩展,甚至报 ORA-00604;更严重的是,snaptime$$ 字段不变,Oracle 仍认为日志“有效”,下次刷新继续写入,空间很快回涨。
安全清理的前提是确认该日志已无任何物化视图使用:
- 查
DBA_REGISTERED_SNAPSHOTS:若LOG_OWNER和LOG_NAME(如MLOG$_SALES)组合无返回,说明无 MV 注册使用 - 查
DBA_MVIEW_LOGS:确认LOG_TABLE和LOG_OWNER没被其他 MV 引用(多个 MV 可共享一个日志) - 执行前务必导出依赖:
SELECT LOG_OWNER, LOG_TABLE, MASTER, ROWIDS, PRIMARY_KEY FROM DBA_MVIEW_LOGS WHERE LOG_TABLE = 'MLOG$_SALES'
确认无引用后,唯一合规操作是:DROP MATERIALIZED VIEW LOG ON owner.sales。
清完不补统计信息和索引,刷新照样慢
删掉旧日志或重建 MV 后,若跳过这三步,性能问题大概率原样复现:
- 立即收集统计信息:
DBMS_STATS.GATHER_TABLE_STATS('SCHEMA_NAME', 'MLOG$_SALES'),否则优化器仍走全表扫描 - 检查并重建关键索引:
CREATE INDEX idx_mlog_snap_seq ON mlog$_sales (snaptime$$, sequence$$),这是 FAST 刷新定位增量记录的命脉 - 若空间仍未释放:注意
MLOG$_xxx不支持SHRINK SPACE,只能导出数据 →DROP MATERIALIZED VIEW LOG→ 重建日志
分区物化视图压缩要对齐基表分区键
单纯给整个 MV 加 COMPRESS 效果有限。真正省空间靠分区级压缩,但前提是分区键必须与基表对齐(aligned),否则无法用 FAST 刷新。
例如基表按 sale_date 范围分区,MV 也得用 TRUNC(sale_date, 'MM') 分区:
- 建 MV 时每个分区单独声明:
PARTITION p_202501 COMPRESS FOR OLTP - 已有分区用:
ALTER MATERIALIZED VIEW mv_name MODIFY PARTITION p_202501 COMPRESS FOR OLTP - 冷分区可直接
DROP PARTITION,比DELETE或TRUNCATE更快、undo/redo 更少
别忘了查基表是否也压缩了——MV 只管自己,基表冗余数据还在吃空间。











