oracle 19c表压缩对dml性能影响取决于压缩类型:compress for oltp延迟几乎无感但高并发可能引发争用,compress for query low则显著拖慢update;误用或统计失真会导致性能下降。

压缩表的DML性能到底慢不慢
Oracle 19c 中启用表压缩后,INSERT、UPDATE、DELETE 并不必然变慢——关键看压缩类型和数据写入模式。19c 的 COMPRESS FOR ALL OPERATIONS 不是在每行插入时实时压缩,而是在块内累积一定数量未压缩行后,触发整块压缩(block-level compression)。这意味着单条 INSERT 的延迟几乎无感,但高并发批量写入时,可能因后台压缩争用导致 enq: TX - row lock contention 或 latch: cache buffers chains 等等待上升。
必须区分 COMPRESS FOR OLTP 和 COMPRESS FOR QUERY LOW
两类压缩机制差异极大,直接影响 DML 行为:
-
COMPRESS FOR OLTP(即COMPRESS FOR ALL OPERATIONS):支持所有 DML,压缩由后台自动触发,对应用透明;但要求表段必须启用ASSM(自动段空间管理),且不能与NOLOGGING同时使用(否则报错ORA-38500: unsupported for compressed tables) -
COMPRESS FOR QUERY LOW:仅适用于只读或低频更新场景;DML 会先解压整块再修改,再重新压缩,开销显著;若在频繁更新的交易表上误用,UPDATE延迟可能翻倍甚至触发大量db file sequential read
实测前必须绕开的三个统计陷阱
直接跑 INSERT /*+ APPEND */ INTO ... SELECT 测速会严重失真,因为直接路径插入(APPEND)在压缩表中默认走传统路径(除非显式加 /*+ APPEND */ 且满足压缩条件),实际执行计划里会出现 LOAD AS SELECT 而非预期的 LOAD TABLE CONVENTIONAL。正确评估要分三步:
- 确认压缩生效:
SELECT table_name, compression, compress_for FROM dba_tables WHERE table_name = 'MY_TAB';,避免误以为启用了却仍是NONE - 禁用自适应执行计划干扰:
ALTER SESSION SET "_optimizer_use_feedback" = FALSE;,否则首次执行采样偏差可能让后续批量 DML 被强制回退到单行路径 - 监控真实块压缩节奏:
SELECT name, value FROM v$sysstat WHERE name LIKE '%compress%';关注heap block compress和heap block uncompress计数,比单纯看响应时间更能反映压缩负载
高频更新场景下压缩反而拖慢的关键信号
当出现以下任意现象,说明压缩正在成为瓶颈,而非优化手段:
-
V$SESSION_EVENT中enq: KO - fast object checkpoint等待突增——表明块压缩触发了频繁的检查点同步 -
DBA_HIST_SEG_STAT显示该表的logical reads未降反升,同时physical reads下降不明显——说明压缩未减少 buffer cache 压力,反而因解压/重压增加了 CPU 开销 - 执行
UPDATE时绑定变量值变化大(如状态字段从'P'切到'C'),但V$SQL_PLAN出现TABLE ACCESS FULL替代原INDEX RANGE SCAN——这是统计信息未适配压缩后数据分布的典型表现,不是压缩本身的问题,但常被误判
压缩从来不是“开就变快”的开关,而是需要和统计信息、访问模式、硬件 IO 能力一起调优的协同策略。最容易被忽略的是:压缩表上的索引是否也重建过?未重建的索引仍指向旧块地址,可能导致逻辑读放大,掩盖压缩收益。











