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 p2 ROW 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 没变,哪怕其他两项都对,也等于没压缩——物理块根本没动过。











