Oracle 19c分区表建表时需为每个分区显式指定COMPRESS FOR OLTP或NOCOMPRESS,不可依赖表空间默认设置;未声明则默认NOCOMPRESS;修改现有分区压缩属性须用ALTER TABLE ... MOVE PARTITION并指定压缩选项。
分区表建表时如何指定各分区的压缩属性
oracle 19c 允许在创建分区表时,为每个分区单独指定 compress 或 nocompress,但必须显式写出,不能依赖表空间默认设置自动继承。关键点是:压缩属性在分区级定义时,优先级高于表空间级,且各分区可互不相同。
常见错误是以为设了表空间 DEFAULT COMPRESS FOR OLTP 就能自动生效——实际不会,分区建表时若没写压缩关键词,Oracle 默认按不压缩处理。
-
COMPRESS FOR OLTP和COMPRESS BASIC都支持分区级指定,但ROW STORE COMPRESS是非法语法,直接报ORA-00922 - 每个
PARTITION子句后可独立加压缩子句,例如:PARTITION par_01 VALUES LESS THAN (...) COMPRESS FOR OLTP - 未声明压缩的分区(如只写
PARTITION par_02 ...)默认为NOCOMPRESS,哪怕表空间已设默认压缩 - 如果某分区需禁用压缩,必须显式写
NOCOMPRESS,不能省略
已有分区表如何修改单个分区的压缩属性
对已存在的分区表,不能直接 ALTER PARTITION ... COMPRESS。必须通过 MOVE 操作重建该分区,并在语句中指定新压缩属性。MOVE 不改变数据逻辑,但会物理重写块并应用新压缩策略。
注意:MOVE 是 DDL 操作,会持有 TX 锁,期间该分区不可更新;若分区很大,可能耗时较长、产生大量 redo。
- 语法:
ALTER TABLE t MOVE PARTITION par_01 COMPRESS FOR OLTP; - 若要取消压缩:
ALTER TABLE t MOVE PARTITION par_02 NOCOMPRESS; - MOVE 后索引会失效,需手动
ALTER INDEX ... REBUILD PARTITION(或加UPDATE INDEXes子句) - 执行前确认表空间有足够空闲空间,因 MOVE 会先写新块再删旧块
验证分区是否真启用对应压缩等级
别只看建表语句写了什么,USER_TAB_PARTITIONS 视图里的 COMPRESSION 和 COMPRESS_FOR 字段才是真实状态。这两个字段反映的是该分区最后一次 MOVE 或创建时实际生效的压缩配置。
- 查当前压缩状态:
SELECT partition_name, compression, compress_for FROM user_tab_partitions WHERE table_name = 'T'; -
COMPRESSION = 'ENABLED'表示启用了压缩,'DISABLED'表示未启用 -
COMPRESS_FOR显示具体类型:'OLTP'、'BASIC'或NULL(未压缩) - 如果发现某分区状态与预期不符,大概率是 MOVE 未成功,或建表时漏写了压缩关键词
OLTP 压缩在高更新频率分区中的隐性风险
给某个频繁更新的分区(比如按时间滚动的“最近7天”热分区)设 COMPRESS FOR OLTP,不是单纯省空间的事。每次 UPDATE 可能触发块内行重组,容易引发链式行(chained rows)和 enq: TX - row lock contention 等等待事件。
尤其当该分区同时存在大量短事务单行更新 + 高并发时,压缩反而可能成为性能瓶颈点。
- 测试阶段必须压测该分区的真实 DML 负载,重点观察
db file sequential read和buffer busy waits等指标变化 - 不要假设“表空间设了 OLTP 就安全”,分区级压缩的代价是独立计算的
- 归档类冷分区用
COMPRESS BASIC更稳妥,它只在批量加载时压缩,对后续只读查询友好
分区压缩的灵活性背后,是每个分区都维护独立的压缩元数据和块格式。这意味着你得为每个分区单独验证、单独维护——没法靠一个表空间设置一劳永逸。


















