表压缩新功能 compress for oltp ROW STORE COMPRESS ADVANCED ONLINE

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$TRANSACTIONV$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.STATUSDBA_IND_PARTITIONS.STATUS 确认全部为 VALID

漏掉这步会导致后续查询走全表扫描或报 ORA-01502

验证压缩是否真实生效的三个硬指标

别只看元数据,盯住这三个值才说明压缩落地了:

  • DBA_SEGMENTS.BYTES:同一分区移动前后对比,MB 级下降才算数(例如从 104 MB → 68 MB)
  • DBA_TAB_PARTITIONS.COMPRESS_FOR:确认是 ADVANCED(不是 BASIC 或空)
  • DBA_TABLESPACE_USAGE_METRICSV$SEGSTAT:观察该分区段的 logical reads 是否随数据密度提升而下降(间接反映压缩带来的 I/O 减少)

如果 BYTES 没变,哪怕其他两项都对,也等于没压缩------物理块根本没动过。