1引言
做为DBA,空间的紧张是常遇到的一个问题,有时一个大的表就会占用几十GB及至上百GB的空间。存储历史数据的表常常都是这样,特别是数据仓库型应用(如经营分析应用)的数据库这样的问题就更加突出。如今,在计算机技术中数据压缩技术已经十分广泛和成熟了。在windows系统中有winrar、winzip,7-zip等等这样的软件,UNIX操作系统中相应的也有compress、gzip这样的压缩命令及软件。这些压缩工具的使用使我们节约了很多的空间,在ORACLE 9i之前的版本我有时在想,ORACLE什么时侯也有类似的功能可以节约空间,提高单位空间的使用价值。期待之余,ORACLE从9i开始羞羞答答的引入表级压缩;10g在部分压缩功能略有增强,例如DataPump源数据的压缩、Rman备份的压缩等,并无本质的改观;Oracle11g才名正言顺的推出Advance Compression组件,支持全方面的压缩,ORACLE的白皮书说,11g采用了更先进的ZLIB要所算法,可以比Oracle10g的压缩算法快上40%,空间需求也将减少20%,压缩率可以达到74.67%。本文将立足于ORACLE9/10g这样的实际应用最多的版本探讨一下ORACLE的压缩技术,并简单介绍一下ORACLE11g的压缩方面的新特征。
[@more@]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.2T_ 28672压缩前与压缩后段统计
压缩前:
SQL> select owner,segment_name,file_id,block_id,blocks 2 from dba_extents 3 where wner='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 wner='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.3dump出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=24offs=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] 434c45 52 4b col 3: [ 3] c2 50 03 col 4: [ 2] c2 09 col 5: [ 7] 77 b40c11 01 01 01 col 6: [ 3] c24a46 col 7: [ 5] 53 4d 49 54 48 bindmp: 00 30 08 17 ff 0e cb c2 50 03 ca c2 09 cf 77 b40c11 01 01 01 cb c24a46 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] 434c45 52 4b col 3: [ 3] c2 4e 59 col 4: [ 2] c20c col 5: [ 7] 77 b7 010c01 01 01 col 6: [ 3] c24f4d col 7: [ 5] 41 44 41 4d 53 bindmp: 00 30 08 17 ff 0e cb c2 4e 59 ca c20ccf 77 b7 010c01 01 01 cb c24f4d 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.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=24offs=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] 434c45 52 4b col 3: [ 3] c2 50 03 col 4: [ 2] c2 09 col 5: [ 7] 77 b40c11 01 01 01 col 6: [ 3] c24a46 col 7: [ 5] 53 4d 49 54 48 bindmp: 00 30 08 17 ff 0e cb c2 50 03 ca c2 09 cf 77 b40c11 01 01 01 cb c24a46 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] 434c45 52 4b col 3: [ 3] c2 4e 59 col 4: [ 2] c20c col 5: [ 7] 77 b7 010c01 01 01 col 6: [ 3] c24f4d col 7: [ 5] 41 44 41 4d 53 bindmp: 00 30 08 17 ff 0e cb c2 4e 59 ca c20ccf 77 b7 010c01 01 01 cb c24f4d 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] 434c45 52 4b col 3: [ 3] c2 50 03 col 4: [ 2] c2 09 col 5: [ 7] 77 b40c11 01 01 01 col 6: [ 3] c24a46 col 7: [ 5] 53 4d 49 54 48 bindmp:2c00 01 08 00 tab 1, row 1, @0x1d94 tl: 5 fb: --H-FL-- lb: 0x0 cc: 8 col 0: [ 2] c11f col 1: [ 2] c2 04 col 2: [ 8] 53 414c45 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] 414c4c45 4e bindmp:2c00 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] 434c45 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 494c4c45 52 bindmp:2c00 01 08 0b end_of_block_dump End dump data blocks tsn: 4 file#: 4 minblk 3860 maxblk 3860 3段压缩的优缺点、限制及性能3.1优点
3.2缺点及限制
3.3性能很多人担心表压缩后性能会有所降低,3.1中已经谈到了查询的性能会有所提升。关于这一点wanghai做了充份的测试,测试表明不论是全表扫描还是通过索引回表扫描压缩表的性能都不会比非压缩表差。至于dml,这是不推荐的,如果非要执行这样的操作,非批量装载操作insert操作之外的普通的insert操作的数据是不进行压缩的,因此压缩表的与常规表的insert性能是一样的。Update操作压缩表时会引发迁移,在浪费空间的同时也会牺牲性能。 |
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22630256/viewspace-1032891/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/22630256/viewspace-1032891/