Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2796657
  • 博文数量: 389
  • 博客积分: 4177
  • 博客等级: 上校
  • 技术积分: 4773
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-16 23:29
文章分类

全部博文(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的文档,具体根据版本的不同可能存储的顺序有所不同.但是基本的方式
都是一样的,存储一个编码和对应的值,这样形成了一个表,另一个表是存储的真实数据的表,但是对应的
栏位中只存放了编码而不是正常的存储的值.

 

 


 

阅读(2403) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~