Oracle表压缩默认关闭,BASIC压缩仅在直路插入时生效,ADVANCED压缩需显式启用且依赖许可,验证须查实际存储而非仅表定义。
Oracle表压缩为什么不是开箱即用
oracle的表压缩默认关闭,即使你用了compress关键字建表,实际生效还取决于压缩类型和操作模式。basic压缩只在insert /*+ append */直路插入(direct-path insert)时触发,普通insert、update、delete完全不压缩——这点常被误认为“压缩失效”。advanced压缩(即oltp压缩)则支持dml实时压缩,但依赖compress for oltp语法且需额外许可。
BASIC压缩只对批量插入有效
常见错误是建表时写CREATE TABLE t1 COMPRESS AS SELECT ...,以为这就压缩了。其实它只是继承了COMPRESS属性,真正压缩发生在数据写入阶段。如果你后续用常规INSERT INTO t1 VALUES (...),数据块里全是未压缩行。
-
INSERT /*+ APPEND */ INTO t1 SELECT * FROM t2:触发BASIC压缩,按数据块内重复值字典编码 -
ALTER TABLE t1 MOVE COMPRESS:可对现有表重组织并压缩,但会锁表、产生大量redo - BASIC压缩不支持索引组织表(IOT)、外部表、临时表
- 压缩后
SELECT COUNT(*)结果不变,但DBA_SEGMENTS.BYTES和DBA_TABLES.BLOCKS会明显下降
ADVANCED压缩需要显式启用且有许可限制
ADVANCED压缩(Oracle 11gR2起称COMPRESS FOR OLTP)在DML过程中自动维护压缩状态,但必须明确指定,不能靠COMPRESS简写。它底层用Hybrid Columnar Compression(HCC)逻辑变体,但仅限Exadata或Oracle Database In-Memory选项授权环境?不完全是——OLTP压缩本身不强制要求Exadata,但COMPRESS FOR QUERY LOW/HIGH等HCC类型才受限。
- 启用方式:
CREATE TABLE t1 COMPRESS FOR OLTP或ALTER TABLE t1 COMPRESS FOR OLTP - UPDATE/DELETE仍会产生少量未压缩行,后台由SMON定期清理(称为“clean up”),可通过
V$SESSION_LONGOPS观察 - 索引不受压缩影响,但压缩表上的索引键值若含重复前缀,可能受益于更紧凑的branch块
- 开启后
LOGGING属性仍生效,归档日志量不会因压缩减少
怎么验证压缩是否真起作用
别只看DBA_TABLES.COMPRESSION字段是ENABLED就放心——它只说明表定义带压缩属性,不反映实际存储状态。真正要看的是数据块内容和段空间使用。
- 查压缩类型:
SELECT COMPRESSION, COMPRESS_FOR FROM DBA_TABLES WHERE TABLE_NAME = 'T1' - 查真实压缩率:
ANALYZE TABLE t1 COMPUTE STATISTICS后检查DBA_TABLES.AVG_ROW_LEN与原始预估对比 - 块级验证:
SELECT COUNT(*) FROM V$BH WHERE OBJD = (SELECT DATA_OBJECT_ID FROM DBA_OBJECTS WHERE OBJECT_NAME = 'T1') AND CLASS# = 1结合DBMS_ROWID.ROWID_BLOCK_NUMBER抽样几行,再用DBMS_COMPRESSION.GET_COMPRESSION_RATIO估算(需提供样本dump文件) - 最直接的办法:
ALTER TABLE t1 MOVE NOCOMPRESS再MOVE COMPRESS FOR OLTP,对比前后DBA_SEGMENTS.BYTES
压缩不是万能的,高并发UPDATE场景下ADVANCED压缩可能增加CPU开销;BASIC压缩则彻底放弃DML友好性。选型前务必在测试库用真实负载压测IO和CPU变化。


















