ALTER TABLE ... MOVE PARTITION ... COMPRESS FOR OLTP 是压缩历史分区唯一有效方式,因 COMPRESS FOR OLTP 仅影响后续 DML 而不重写旧数据;必须启用行迁移、确保主键或唯一约束(ONLINE 时)、避免长事务阻塞,并重建局部索引后验证实际字节变化。

直接对历史分区执行 ALTER TABLE ... MOVE PARTITION ... COMPRESS FOR OLTP 是最有效、最可控的方式;只设表空间默认压缩或建表时加 COMPRESS,对已有分区完全无效。
为什么 ALTER TABLE COMPRESS FOR OLTP 不压缩已有分区数据
Oracle 的 COMPRESS FOR OLTP(等价于 ROW STORE COMPRESS ADVANCED)在分区表上不是“自动扫描并重写旧数据”,它只影响后续 DML:新插入的行、被更新后重新落盘的行,才可能触发块级压缩。已存在的数据块保持原样,哪怕你执行了 ALTER TABLE t COMPRESS FOR OLTP,也只是改了元数据,不碰物理块。
- 查
DBA_TAB_PARTITIONS.COMPRESS_FOR可能显示ADVANCED,但那只是“未来生效”的承诺,不是已完成压缩 - 真正压缩必须触发物理重写——核心动作是
MOVE PARTITION,不是MODIFY PARTITION或开关式启用 - 分区级压缩属性可独立设置,
P1和P2可以一个启用、一个关闭,全局设置不覆盖
执行 MOVE PARTITION COMPRESS FOR OLTP 的关键前提
跳过这三步,命令会报错或静默失败:
- 必须先启用行迁移:
ALTER TABLE t ENABLE ROW MOVEMENT;否则MOVE会报ORA-14102 - 若使用
ONLINE(12cR2+ 推荐),表必须有主键或唯一约束,否则局部索引重建可能出错 - 确保目标分区当前无长事务:查
V$TRANSACTION和V$SESSION中关联的TADDR,避免MOVE被 TX 锁阻塞数小时
示例命令(在线、安全):
ALTER TABLE sales_hist MOVE PARTITION p_202401 ROW STORE COMPRESS ADVANCED ONLINE;
MOVE 后必须重建局部索引,且要验证效果
MOVE PARTITION 会让该分区上的局部索引失效(STATUS = UNUSABLE),全局索引虽默认维护,但状态需人工确认。
- 重建局部索引:
ALTER INDEX sales_hist_idx REBUILD PARTITION p_202401 - 验证是否真压缩:
SELECT PARTITION_NAME, COMPRESS_FOR, BYTES/1024/1024 MB FROM DBA_SEGMENTS WHERE SEGMENT_NAME = 'SALES_HIST' AND PARTITION_NAME = 'P_202401' - 别只看
USER_TABLES.COMPRESSION字段——它反映的是表级定义,不是分区实际压缩状态
容易被忽略的压缩陷阱
历史分区压缩不是“一劳永逸”:
-
COMPRESS BASIC对普通 INSERT/UPDATE 完全无效,只响应INSERT /*+ APPEND */和CTAS,千万别混用 - 压缩后空间反而变大?常见于低重复度数据(如 UUID 主键 + 随机时间戳),压缩算法找不到足够模式,块头开销反超收益
- CLOB/BLOB 列内容从不参与行压缩,想压它们必须走
SECUREFILE COMPRESS单独定义,且无法对已有 BASICFILE 列在线升级
真正省空间的关键不在语法多漂亮,而在选对分区、确认数据特征、做完 MOVE 后立刻验证字节数变化——否则你只是改了几个字典字段而已。


















