Oracle如何压缩表数据节省空间_使用BASIC与ADVANCED压缩
Oracle表压缩为什么不是开箱即用
很多朋友初次接触Oracle表压缩时,可能会遇到一个困惑:明明建表时加了COMPRESS关键字,为什么实际存储空间没怎么减少?这里需要澄清一个关键点:Oracle的表压缩功能默认是关闭的,即使你使用了compress关键字,其最终能否生效,还取决于你选择的压缩类型以及具体的数据操作方式。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
简单来说,BASIC压缩只在特定的insert /*+ append */(直路插入)操作时才会触发,对于常规的insert、update和delete,数据块里的行是完全不压缩的——这个特性常常被误认为是“压缩功能失效了”。而更高级的ADVANCED压缩(即OLTP压缩)虽然支持DML操作的实时压缩,但它需要显式地使用compress for oltp语法来启用,并且依赖于相应的数据库许可。
Oracle表压缩默认关闭,BASIC压缩仅在直路插入时生效,ADVANCED压缩需显式启用且依赖许可,验证须查实际存储而非仅表定义。
BASIC压缩只对批量插入有效
一个常见的误解发生在使用CREATE TABLE t1 COMPRESS AS SELECT ...这样的语句时。你以为表建好数据就压缩了?其实不然。这条语句只是让新表继承了COMPRESS这个属性,真正的压缩动作,要等到数据写入的那一刻才会发生。如果你后续使用普通的INSERT INTO t1 VALUES (...)一条条插入数据,那么这些数据块里存放的,依然是未经压缩的原始行。
那么,BASIC压缩究竟在什么场景下工作呢?
- 批量直路插入:使用
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压缩需要显式启用且有许可限制
如果你需要一种对DML操作更友好的压缩方式,那么ADVANCED压缩(从Oracle 11gR2起称为COMPRESS FOR OLTP)是更好的选择。它能在INSERT、UPDATE、DELETE过程中自动维护压缩状态。但是,它必须被明确指定,不能简单地用COMPRESS来代替。
这里有个许可相关的问题需要厘清:ADVANCED压缩底层采用了混合列式压缩(HCC)的逻辑变体,但它本身并不强制要求Exadata环境。真正强制绑定Exadata或Oracle Database In-Memory选项授权的,是COMPRESS FOR QUERY LOW/HIGH这类更高级的HCC压缩类型。
启用和使用ADVANCED压缩时,有几个细节值得关注:
- 启用方式:建表时使用
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.A VG_ROW_LEN(平均行长),与根据表结构预估的原始行长度进行对比。 - 块级深度验证:这需要更专业的操作。首先结合
V$BH和DBA_OBJECTS视图找到表的对象ID和对应的缓存块,然后利用DBMS_ROWID包抽样获取具体行所在的块号。最准确的方法是使用DBMS_COMPRESSION.GET_COMPRESSION_RATIO过程进行分析,但这通常需要提供数据块的dump文件。 - 最直接的对比法:如果条件允许,可以做一个简单的测试:先执行
ALTER TABLE t1 MOVE NOCOMPRESS取消压缩,再执行ALTER TABLE t1 MOVE COMPRESS FOR OLTP重新启用压缩,然后分别查询DBA_SEGMENTS.BYTES,对比前后两次的字节数变化。
最后必须强调,压缩并非万能灵药。在高并发的UPDATE场景下,ADVANCED压缩可能会带来额外的CPU开销;而BASIC压缩则几乎完全牺牲了对日常DML操作的友好性。因此,在生产环境选型前,务必在测试库中用真实的业务负载进行压测,充分评估其对I/O和CPU资源的具体影响。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
mysql执行sql语句时内存溢出_如何设置排序区buffer优化内存使用
MySQL排序内存溢出?别慌,先搞懂sort_buffer_size怎么调 sort_buffer_size并非越大越好,盲目调高易引发OOM;它按需分配、每连接独占,建议会话级设为4MB而非全局调整,并优先优化索引避免filesort。 MySQL排序内存不足报 Out of memory 怎么调
mysql如何清理过大的binlog日志_设置expire_logs_days自动删除
MySQL Binlog清理:为什么设置了过期天数,日志文件却纹丝不动? 不少DBA都遇到过这个令人困惑的场景:明明在配置文件里白纸黑字地设置了expire_logs_days = 7,重启后检查变量也确认生效了。可一周过去,磁盘空间告急,一查发现那些本该被自动清理的旧binlog文件,居然还老老实
mysql主从同步报错1062怎么解决_使用set global sql_slave_skip_counter跳过错误
MySQL主从同步报错1062:从应急跳转到根治数据冲突的完整指南 遇到主从同步卡在1062错误,很多DBA的第一反应就是“跳过它”。但跳过之后呢?问题往往卷土重来。今天,我们就来彻底拆解这个经典的“Duplicate entry”冲突,把应急操作和根治方案一次讲清楚。 MySQL主从同步报错106
MySQL生产环境误操作drop表_通过Binlog闪回恢复数据
MySQL生产环境误删表数据?别急,利用Binlog日志实现精准闪回恢复 在MySQL数据库运维中,最令人紧张的场景莫过于生产环境误执行了DROP TABLE命令。面对突发状况,保持冷静是关键。只要数据库满足两个核心条件,被删除的数据就有极高的恢复可能性。这两个必要条件是什么?即MySQL的二进制日
mysql如何解决由于外键导致的更新死锁_在高性能场景下拆除外键
MySQL外键:高性能场景下的隐形死锁制造者与安全拆除指南 先明确一个核心结论:在高并发写入的场景下,数据库外键约束极易成为性能瓶颈和死锁的源头。简单来说,外键的UPDATE操作会因校验参照完整性而对关联记录加共享锁(S锁);若要安全拆除,则需遵循确认依赖、手动校验、在线删除三步走;拆除后,必须通过
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

