全部博文(389)
分类: Oracle
2014-02-07 21:34:38
oracle 压缩
我们知道压缩好处多,特别是在数据仓库的场景,更新的情况比较少,可以存放更多的数据,同时读取相同的数据行
所需要的io次数更少。缺点是增加了cpu利用,因为在存放或是读取数据的时候需要重组数据行.
压缩主要的方式有:compress basic,index, oltp。前两项是系统默认就有选项,而oltp则需要advance compression许
可证.compress basic主要是适用于只读的数据处理,且是append的操作.正常的dml是不会被压缩的.来看看几个例子
A,
SQL>create table t1
compress basic
as select * from dba_tables where rownum=0;
SQL> insert into t1 select * from dba_tables;
SQL>commit;
SQL> exec dbms_stats.gather_table_stats(ownname=>'C##FRANK',tabname=>'T1');
SQL> select table_name,owner,blocks from dba_tables where owner='C##FRANK';
TABLE_NAME OWNER BLOCKS
-------------------- -------------------- ----------
T1 C##FRANK 80
可以看到正常的insert 是的不会被compress的.
B,
SQL>create table t2
compress basic
as select * from dba_tables where rownum=0;
SQL> insert /*+ append */ into t2 select * from dba_tables;
SQL>commit;
SQL> exec dbms_stats.gather_table_stats(ownname=>'C##FRANK',tabname=>'T2');
SQL> select table_name,owner,blocks from dba_tables where owner='C##FRANK' and table_name='T2';
TABLE_NAME OWNER BLOCKS
-------------------- -------------------- ----------
T2 C##FRANK 13
例B中通过append进行insert时,会以compress的方式进行insert.
C,
SQL>create table t3
as select * from dba_tables where rownum=0
SQL> insert into t3 select * from dba_tables;
SQL>commit;
SQL> exec dbms_stats.gather_table_stats(ownname=>'C##FRANK',tabname=>'T3');
SQL> alter table t3 compress basic;
SQL> select table_name,owner,blocks from dba_tables where owner='C##FRANK' and table_name='T3';
TABLE_NAME OWNER BLOCKS
-------------------- -------------------- ----------
T3 C##FRANK 88
SQL> alter table t3 move;
SQL> exec dbms_stats.gather_table_stats(ownname=>'C##FRANK',tabname=>'T3');
SQL> select table_name,owner,blocks from dba_tables where owner='C##FRANK' and table_name='T3';
TABLE_NAME OWNER BLOCKS
-------------------- -------------------- ----------
T3 C##FRANK 14
例C,首先通过普通的方式创建表,然后insert,再更改为compress basic,可以看出更改 compress basic并不会
对原来的数据有效,只能通过move的方式重组数据才会对来的原来的数据进行压缩.
D,
SQL> create table t4
2 compress basic
3 as select * from dba_tables;
SQL> exec dbms_stats.gather_table_stats(ownname=>'C##FRANK',tabname=>'T4');
SQL> select table_name,owner,blocks from dba_tables where owner='C##FRANK' and table_name='T4';
TABLE_NAME OWNER BLOCKS
-------------------- -------------------- ----------
T4 C##FRANK 13
例D,通过在CATS时定义compress basic的方式,这样新表中的数据也是被压缩了.
oracle的压缩并不是真正传统意义上的压缩,而是通过对块进行重组来存储和读出数据块.在每个块头都有一个字典,对于每个
重复值,存放了编码和值,在行的数据中只存储的编码,通过编码可以读取对应的字典中的数据.
SQL> select dbms_rowid.rowid_block_number(rowid),
2 dbms_rowid.rowid_relative_fno(rowid)
3 from t4 where table_name='TYPE_MISC$'
4 ;
DBMS_ROWID.ROWID_BLOCK_NUMBER( DBMS_ROWID.ROWID_RELATIVE_FNO(
------------------------------ ------------------------------
323 6
tab 1, row 0, @0x1af1
tl: 28 fb: --H-FL-- lb: 0x0 cc: 60
col 0: *NULL*
col 1: [ 5] 56 41 4c 49 44
col 2: [ 2] c1 02
col 3: [ 6] c5 16 30 31 25 2e
col 4: *NULL*
.......
col 59: [10] 54 59 50 45 5f 4d 49 53 43 24 --此处存放的是表名
bindmp: 2c 00 07 04 28 ca c1 30 cb c2 1b 2c cb c2 1b 2c 58 d2 54 59 50 45 5f 4d 49 53 43 24
从数据块的dump来看,里面包含了一个数据字典,这样加上原来的表数据,oracle在该块存放了两个表
ntab=2 --表的数量
0x52:pti[0] nrow=131 offs=0
0
x56:pti[1] nrow=249 offs=131
通过转换,oracle可以重组原来的数据.但是随着对表的扫描增加,开销越大,因为每次都需要重组数据.
关于bindmp的解码可能需要oracle的文档,具体根据版本的不同可能存储的顺序有所不同.但是基本的方式
都是一样的,存储一个编码和对应的值,这样形成了一个表,另一个表是存储的真实数据的表,但是对应的
栏位中只存放了编码而不是正常的存储的值.