本文将立足于ORACLE9/10g这样的实际应用最多的版本探讨一下ORACLE的压缩技术,并简单介绍一下ORACLE11g的压缩方面的新特征。
[@more@]
1 引言
作为DBA,空间的紧张是常遇到的一个问题,有时一个大的表就会占用几十GB及至上百GB的空间,存储历史数据的表常常都是这样,特别是数据仓库型应用(如经营分析应用)的数据库这样的问题就更加突出。如今,在计算机技术中数据压缩技术已经十分广泛和成熟了。在windows系统中有winrar、winzip,7-zip等等这样的软件,UNIX操作系统中相应的也有compress、gzip这样的压缩命令及软件。这些压缩工具的使用使我们节约了很多的空间,在ORACLE 9i之前的版本我有时在想,ORACLE什么时候也有类似的功能可以节约空间,提高单位空间的使用价值。期待之余,ORACLE从9i开始羞羞答答的引入表段级压缩;10g在部分压缩功能略有增强,例如DataPump源数据的压缩、Rman备份的压缩等,并无本质的改观;Oracle11g才大张旗鼓的推出相应Compression组件,支持全方面的压缩。本文将立足于ORACLE9/10g这样的实际应用最多的版本探讨一下ORACLE的压缩技术,并简单介绍一下ORACLE11g的压缩方面的新特征。
2 数据段压缩实现原理
2.1 原理简单描述
ORACLE的数据段压缩技术可以理解为“数据块”级压缩技术,也就是说是针对Block级别的数据压缩。它是在Block中引入记号表(symbol表),Block中的重复数据在symbol中用一个项(指针)表示,即块中相同的ROW只存储一条,从而节约了空间。
2.2 压缩数据块的存储结构
2.2.1 建一张包含28672行数据的表T_ 28672
SQL> show user USER is "SCOTT" SQL> SQL> select count(*) from t_28672; COUNT(*) ---------- 28672 |
2.2.2 T_ 28672压缩前与压缩后段统计
压缩前:
SQL> select owner,segment_name,file_id,block_id,blocks 2 from dba_extents 3 where owner='SCOTT' 4 and segment_name='T_28672' 5 order by block_id 6 / OWNER SEGMENT_NAME FILE_ID BLOCK_ID BLOCKS ----- -------------------- ---------- ---------- ---------- SCOTT T_28672 4 3729 8 SCOTT T_28672 4 3737 8 SCOTT T_28672 4 3745 8 SCOTT T_28672 4 3753 8 SCOTT T_28672 4 3761 8 SCOTT T_28672 4 3769 8 SCOTT T_28672 4 3777 8 SCOTT T_28672 4 3785 8 SCOTT T_28672 4 3793 8 SCOTT T_28672 4 3801 8 SCOTT T_28672 4 3809 8 SCOTT T_28672 4 3817 8 SCOTT T_28672 4 3825 8 SCOTT T_28672 4 3833 8 SCOTT T_28672 4 3841 8 SCOTT T_28672 4 3849 8 SCOTT T_28672 4 3977 128 17 rows selected. SQL> |
执行表压缩:
SQL> alter table T_28672 move COMPRESS; Table altered. |
压缩后:
SQL> select owner,segment_name,file_id,block_id,blocks 2 from dba_extents 3 where owner='SCOTT' 4 and segment_name='T_28672' 5 order by block_id 6 / OWNER SEGMENT_NAME FILE_ID BLOCK_ID BLOCKS ----- -------------------- ---------- ---------- ---------- SCOTT T_28672 4 3857 8 SCOTT T_28672 4 3865 8 SCOTT T_28672 4 3873 8 SCOTT T_28672 4 3881 8 SCOTT T_28672 4 3889 8 SCOTT T_28672 4 3897 8 6 rows selected. SQL> |
简单总结:
从压缩前后段的数量上看,压缩还是相当节约空间的,17个区压缩成6个区,2倍的压缩比。
2.2.3 dump出file 4 block 3860块
SQL> alter system dump datafile 4 block 3860; System altered. |
2.2.4 结构分析
需要说明的是,如下的内容为完整.trc的节选,有关于block dump内容更详细的解释可以参照“ DSI402e Data Types and Block Structures”,本文只关注与压缩有关的部分。
2.2.4.1 data header部分
此部分是总结的部分,记录了块中有多少行的数据,列存储的顺序,记录表中记录的条数及重复记录的条数等信息。
data_block_dump,data header at 0x1103ff07c =============== tsiz: 0x1f80 hsiz: 0x5b0 pbl: 0x1103ff07c bdba: 0x01000f14 76543210 flag=-0------ *flag为0表示是压缩块 ntab=2 *ntab表述数据块中表的数量,普通表的数据块中这个值是1, 而压缩表大于1 nrow=700 *nrow表示该数据块中的记录数,此项表明该块中含700条记录 frre=-1 fsbo=0x5b0 fseo=0x106a avsp=0x2a tosp=0x2a r0_9ir2=0x0 *9ir2表示的是这项压缩功能起始的版本 mec_kdbh9ir2=0xe 76543210 shcf_kdbh9ir2=---------- 76543210 flag_9ir2=--R---OC fcls_9ir2[9]={ 0 32768 32768 32768 32768 32768 32768 32768 32768 } perm_9ir2[8]={ 6 7 2 3 5 4 1 0 } *表示实际存储字段顺序也就是说,后面物理存储的顺序COL6,COL7,COL2... 0x30:pti[0] nrow=24 offs=0 *记号表中非重复的记录中有24条 0x34:pti[1] nrow=676 offs=24 *重复的记录有676行 0x38:pri[0] offs=0x1f14 ... ... ... ... 0x5ac:pri[698] offs=0x106f 0x5ae:pri[699] offs=0x106a |
2.2.4.2 非重复的各条记录
共24行的数据,部分数据省略掉
block_row_dump: tab 0, row 0, @0x1f14 tl: 31 fb: --H-FL-- lb: 0x0 cc: 8 *fb->flag byte H->header F->first L->last *cc->column count(列数量) col 0: [ 2] c1 15 *列长度为2,类型为c115 col 1: *NULL* col 2: [ 5] 43 4c 45 52 4b col 3: [ 3] c2 50 03 col 4: [ 2] c2 09 col 5: [ 7] 77 b4 0c 11 01 01 01 col 6: [ 3] c2 4a 46 col 7: [ 5] 53 4d 49 54 48 bindmp: 00 30 08 17 ff 0e cb c2 50 03 ca c2 09 cf 77 b4 0c 11 01 01 01 cb c2 4a 46 cd 53 4d 49 54 48 *0030表示为0x0030转为十进制为48,表示这一压缩行供给48行使用 *08表示列的数量,即为8列 tab 0, row 1, @0x1ef5 tl: 31 fb: --H-FL-- lb: 0x0 cc: 8 col 0: [ 2] c1 15 col 1: *NULL* col 2: [ 5] 43 4c 45 52 4b col 3: [ 3] c2 4e 59 col 4: [ 2] c2 0c col 5: [ 7] 77 b7 01 0c 01 01 01 col 6: [ 3] c2 4f 4d col 7: [ 5] 41 44 41 4d 53 bindmp: 00 30 08 17 ff 0e cb c2 4e 59 ca c2 0c cf 77 b7 01 0c 01 01 01 cb c2 4f 4d cd 41 44 41 4d 53 ... ... ... ... tab 0, row 23, @0x1f7b tl: 5 fb: --H-FL-- lb: 0x0 cc: 1 col 0: [ 2] c1 15 |
2.2.4.3 重复的各条记录
相同的记录会有同样的指针,例如在本例中,row1与row 15,23,49指向的都是同一个位置。
bindmp: 00 05 ca c1 15 *指向记号表中记录的指针,相同的记录同样的指针 tab 1, row 0, @0x1d99 tl: 5 fb: --H-FL-- lb: 0x0 cc: 8 col 0: [ 2] c1 15 col 1: *NULL* col 2: [ 5] 43 4c 45 52 4b col 3: [ 3] c2 50 03 col 4: [ 2] c2 09 col 5: [ 7] 77 b4 0c 11 01 01 01 col 6: [ 3] c2 4a 46 col 7: [ 5] 53 4d 49 54 48 bindmp: 2c 00 01 08 00 tab 1, row 1, @0x1d94 tl: 5 fb: --H-FL-- lb: 0x0 cc: 8 col 0: [ 2] c1 1f col 1: [ 2] c2 04 col 2: [ 8] 53 41 4c 45 53 4d 41 4e col 3: [ 3] c2 4d 63 col 4: [ 2] c2 11 col 5: [ 7] 77 b5 02 14 01 01 01 col 6: [ 3] c2 4b 64 col 7: [ 5] 41 4c 4c 45 4e bindmp: 2c 00 01 08 07 ... ... ... ... tab 1, row 675, @0x106a tl: 5 fb: --H-FL-- lb: 0x0 cc: 8 col 0: [ 2] c1 0b col 1: *NULL* col 2: [ 5] 43 4c 45 52 4b col 3: [ 3] c2 4e 53 col 4: [ 2] c2 0e col 5: [ 7] 77 b6 01 17 01 01 01 col 6: [ 3] c2 50 23 col 7: [ 6] 4d 49 4c 4c 45 52 bindmp: 2c 00 01 08 0b end_of_block_dump End dump data blocks tsn: 4 file#: 4 minblk 3860 maxblk 3860 |
3 段压缩的优缺点、限制及性能
3.1 优点
节省存储空间:这也是ORACLE实现段数据压缩的目的所在,随着数据的海量,历史数据的不断的堆积,段压缩技术在节省空间的同时也节省了单位历史数据的存储成本。
性能会有提升:段压缩针对的都应该是历史数据,这样的数据的特点是海量、不变更一般只用于查询,这里所说的性能的提升是在CPU不是瓶颈的前提下,且是查询性能的提升。因为表段被压缩后其所占的数据块会大量的减少,单次的IO会读取更多的block,也因此会减少对buffer cache的占用。段压缩技术会提升IO的性能,如今cpu不断的加速,从双核到四核不断的加速,ibm p6的cpu也已经问世,也因此时间换空间的优化技术也越来越流行。
3.2 缺点及限制
会增加些额外的cpu的负担:上面已经提到,ORACLE段压缩技术是时间换空间的一种体现,存储空间的减少势必会导致建立压缩段和查询数据时压缩及解压缩时cpu的消耗。
表压缩不支持超过255列
以BasicFile(相对于11g推出的SecureFiles而言)方式存储的LOB型数据段在表压缩时是不会被压缩的,11g推出的SecureFiles支持LOB的压缩,这方面可以参照11g的联机文档。
ORACLE11g之前的版本只会在批量装载时对数据进行压缩:虽然在Oracle9i中引入了段压缩技术,但只能对批量装载操作(比如sql*loader直接路径装载,CTAS,insert加append提示等)涉及的数据进行压缩,普通的DML操作的数据是无法压缩的,这应该是对于写操作的压缩难题没有解决的缘故。
索引组织表及含有overflow段的表或分区表是不支持表压缩的。
不能显示的(explicitly)为hash分区及hash和list子分区定设定压缩选项,这些分区的压缩选项可以从表空间、表或分区的压缩属性继承过来。
外部表和是cluster组成部分的表是不支持压缩的。
段压缩技术适用于数据仓库这样的应用,一张表压缩后最好避免DML类型的操作,特别是update的操作,update操作会导致行迁移的发生,使得压缩表可能比原表占用的空间还大,所以切忌对压缩表做update操作,这样的技术应该用在合适的地方。
3.3 性能
很多人担心表压缩后性能会有所降低,3.1中已经谈到了查询的性能会有所提升。关于这一点wanghai做了充份的测试,测试表明不论是全表扫描还是通过索引回表扫描压缩表的性能都不会比非压缩表差。至于dml,这是不推荐的,如果非要执行这样的操作,非批量装载操作insert操作之外的普通的insert操作的数据是不进行压缩的,因此压缩表的与常规表的insert性能是一样的。Update操作压缩表时会引发迁移,在浪费空间的同时也会牺牲性能。
4 压缩前如何得到表的压缩比?
4.1 压缩比定义
在要不要对一个表压缩时,很多DBA很迷惑,因为不知道这个表压缩后是不是会节约空间。通俗的说来就是,如果压缩完的表与没压缩时空间占用一样大就没有必要折腾了。如果在压缩前能知道一个表的压缩比就好了,Carl Dudley在一篇文章写一了个计算压缩比的函数,压缩比可以这样的定义:
压缩比=压缩前表中的block的数量 / 压缩后表中block的数量
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/717880/viewspace-999762/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/717880/viewspace-999762/