ALTER TABLE ... COMPRESS FOR OLTP 对已有分区无效,因仅设置元数据标记而不重写物理块;压缩已有数据须用 MOVE PARTITION ... ROW STORE COMPRESS ADVANCED ONLINE 并重建索引。
不能直接用 alter table ... compress for oltp 让已有分区数据变小
------它只影响后续 dml,不重写物理块。
为什么 ALTER TABLE COMPRESS FOR OLTP 对已有分区无效
执行 ALTER TABLE t1 COMPRESS FOR OLTP 后,DBA_TAB_PARTITIONS.COMPRESS_FOR 会显示 ADVANCED,但分区段(segment)大小完全不变。这是因为该语句仅设置"未来插入/更新时启用压缩"的元数据标记,Oracle 不会自动扫描并重写已存在的数据块。常见误判是看到 COMPRESS_FOR 变了就以为压缩生效了,实际空间一点没省。
- 已有数据仍按原格式存储,块内无压缩、无空闲空间回收
- 新插入或更新的行才会被压缩进新块(可能触发
ROW MOVEMENT) - 若表无主键/唯一约束,后续
MOVE PARTITION可能导致全局索引失效
在线压缩单个分区必须用 MOVE PARTITION + ONLINE
真正压缩已有数据,必须触发物理重写。Oracle 12c 支持在线移动分区,对业务影响可控,但需满足前提条件:
- 先执行
ALTER TABLE t1 ENABLE ROW MOVEMENT(否则报错ORA-14102) - 目标分区不能有长事务阻塞:查
V$TRANSACTION和V$SESSION确认无未提交 DML - 使用
ROW STORE COMPRESS ADVANCED ONLINE(不是COMPRESS FOR OLTP,后者在MOVE中不被识别) - 命令示例:
ALTER TABLE t1 MOVE PARTITION p2ROW STORE COMPRESS ADVANCED ONLINE;
执行期间支持 SELECT/INSERT/UPDATE/DELETE,但会短暂持有 TX 锁(通常毫秒级),且要求表有主键或唯一索引以保证全局索引可维护。
MOVE 后必须重建局部索引,全局索引要检查状态
局部索引(LOCAL)不会自动跟随分区移动,必须显式重建对应分区:
ALTER INDEX idx_local REBUILD PARTITION p2;- 全局索引(
GLOBAL)默认自动维护,但可能进入UNUSABLE状态(尤其当未启用ROW MOVEMENT或约束缺失时) - 务必查
DBA_INDEXES.STATUS和DBA_IND_PARTITIONS.STATUS确认全部为VALID
漏掉这步会导致后续查询走全表扫描或报 ORA-01502。
验证压缩是否真实生效的三个硬指标
别只看元数据,盯住这三个值才说明压缩落地了:
DBA_SEGMENTS.BYTES:同一分区移动前后对比,MB 级下降才算数(例如从 104 MB → 68 MB)DBA_TAB_PARTITIONS.COMPRESS_FOR:确认是ADVANCED(不是BASIC或空)DBA_TABLESPACE_USAGE_METRICS或V$SEGSTAT:观察该分区段的logical reads是否随数据密度提升而下降(间接反映压缩带来的 I/O 减少)
如果 BYTES 没变,哪怕其他两项都对,也等于没压缩------物理块根本没动过。