ALTER TABLE MOVE PARTITION COMPRESS 是压缩存量数据的唯一可靠方式,需显式指定COMPRESS、启用ROW MOVEMENT、处理位图索引与局部索引,并验证空间释放效果。

ALTER TABLE MOVE PARTITION COMPRESS 不会自动重写已有数据
直接执行 ALTER TABLE t1 COMPRESS FOR OLTP 只影响后续 INSERT/UPDATE,对已存在的分区数据完全无效。历史分区仍以原始未压缩格式存储,空间不会释放。
必须触发物理重写才能压缩存量数据,最可靠的方式是 MOVE PARTITION —— 它会读取原分区所有行、按新压缩格式重组、写入新数据块。
- 不加
COMPRESS关键字(如只写MOVE PARTITION p1)等于白跑一趟,数据不变 -
COMPRESS FOR OLTP和ROW STORE COMPRESS ADVANCED等价,Oracle 12c+ 推荐用后者 - 若目标分区含位图索引(
BITMAP INDEX),MOVE会失败,需先DROP或改为 B-tree
在线压缩需要 ENABLE ROW MOVEMENT 且依赖主键/唯一约束
MOVE PARTITION ... ONLINE 能减少业务中断,但不是无条件可用:表必须有主键或唯一约束,否则在线移动时无法正确维护全局索引,可能报错 ORA-14086。
执行前必须先启用行迁移:
ALTER TABLE t1 ENABLE ROW MOVEMENT;
- 没这句就执行
ONLINE移动,会直接报ORA-14552(无法在事务中执行 DDL) - 即使有主键,若该主键被禁用(
DISABLE状态),仍会失败,需先ENABLE - 局部索引(
LOCAL INDEX)会在移动后自动失效,必须显式REBUILD PARTITION
大分区压缩前要检查长事务和锁冲突
对 TB 级分区执行 MOVE 期间会持有 TX 锁,若此时有未提交的 DML(尤其长时间运行的批量更新),会导致阻塞甚至死锁。
建议用以下语句确认无活跃事务干扰:
SELECT s.sid, s.serial#, s.sql_id, s.event FROM v$session s WHERE s.sid IN ( SELECT sid FROM v$lock WHERE type='TX' AND request>0 );
- 重点关注
event列是否含enq: TX或row cache lock - 不要只查
V$TRANSACTION,它只显示已开始的事务,漏掉未发INSERT但已持锁的会话 - 生产环境建议避开高峰时段,并提前通知相关应用暂停写入
压缩后必须验证并清理残留空间
移动分区只是把数据重写进新块,原数据块仍留在段中,高水位线(HWM)没降,表空间不会自动回收。
验证压缩效果用:
SELECT partition_name, compress_for, bytes/1024/1024 mb FROM dba_segments WHERE segment_name = 'T1' AND partition_name = 'P2';
- 对比移动前后
MB值,下降 30%+ 才算有效 - 若
COMPRESS_FOR仍是NONE,说明MOVE没带COMPRESS参数 - 真正释放磁盘空间要靠
ALTER DATABASE DATAFILE ... RESIZE,但必须先做COALESCE表空间
压缩不是一锤子买卖,每个分区都是独立对象,属性、索引状态、空间利用率都得单独过一遍——漏掉一个分区,就等于白压了。


















