ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Oracle 10g数据表压缩的一些细节(上)

Oracle 10g数据表压缩的一些细节(上)

原创 Linux操作系统 作者:realkid4 时间:2012-03-25 19:22:40 0 删除 编辑

 

Oracle 11g中,Advanced Compression是一个重要引入的新特性。Advanced Compression针对OLTP下的数据对象、Dataguard Redo Log等进行了较大程度的优化。在笔者之前的文章中,也针对此项特性进行了浅析。

 

目前,还有很多系统是运行在Oracle 10g乃至9i下,对这些系统而言,Oracle压缩有一些什么特性呢?本篇一起来探讨。

 

1、环境准备

 

我们选择Oracle 10gR2作为环境,同时准备原始数据表t_source,作为参照对象。

 

 

SQL> select * from v$version;

BANNER

----------------------------------------------------------------

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

PL/SQL Release 10.2.0.1.0 - Production

CORE     10.2.0.1.0       Production

 

 

准备数据,观察在未使用10g压缩特性情况下,数据空间使用情况。

 

 

SQL> create table t_source as select * from dba_objects where wner='SCOTT' or wner='SYSMAN';

Table created

 

SQL> select count(*) from t_source;

  COUNT(*)

----------

      1367

 

SQL> exec dbms_stats.gather_table_stats(user,'T_SOURCE',cascade => true);

PL/SQL procedure successfully completed

 

--段级别空间使用分析

SQL> select HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS, EXTENTS from dba_segments where wner='SCOTT' and segment_name='T_SOURCE';

HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS    EXTENTS

----------- ------------ ---------- ---------- ----------

          4           19     196608         24          3

 

 

SQL> select NUM_ROWS, BLOCKS, Compression from dba_tables where wner='SCOTT' and table_name='T_SOURCE';

  NUM_ROWS     BLOCKS COMPRESSION

---------- ---------- -----------

      1367         23 DISABLED

 

 

在利用所有行rowid情况,分析每个数据块的平均容纳行数。

 

 

SQL> select dbms_rowid.rowid_relative_fno(rowid) fno, dbms_rowid.rowid_block_number(rowid) bno, count(*) from t_source group by dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid) order by bno;

 

       FNO        BNO   COUNT(*)

---------- ---------- ----------

         4         20         46

         4         21         76

         4         22         76

         4         23         74

         4         24         78

         4       4105         73

         4       4106         71

         4       4107         71

         4       4108         73

         4       4109         77

         4       4110         76

         4       4111         74

         4       4112         73

         4       4114         77

         4       4115         74

         4       4116         75

         4       4117         45

         4       4119         81

         4       4120         77

19 rows selected

 

 

SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where wner='SCOTT' and segment_name='T_SOURCE';

 

 EXTENT_ID    FILE_ID   BLOCK_ID      BYTES     BLOCKS

---------- ---------- ---------- ---------- ----------

         0          4         17      65536          8 第一个分区

         1          4       4105      65536          8

         2          4       4113      65536          8

 

 

从上面准备的数据表t_source的情况看,在没有使用压缩的情况下分配三个分区共24个数据块。1367条记录分布在19个数据块上,平均每个数据块容纳大约70-80行记录。

 

2、压缩表建立实验

 

下面建立压缩数据表。在建表的第一分区分配的时候,就采用压缩方式进行。

 

 

SQL> create table t_compress compress as select * from t_source;

Table created

 

SQL> exec dbms_stats.gather_table_stats(user,'T_COMPRESS',cascade => true);

PL/SQL procedure successfully completed

 

 

SQL> select HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS, EXTENTS from dba_segments where wner='SCOTT' and segment_name='T_COMPRESS';

 

HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS    EXTENTS

----------- ------------ ---------- ---------- ----------

          4         4123     131072         16          2

 

 

SQL> select NUM_ROWS, BLOCKS, Compression from dba_tables where wner='SCOTT' and table_name='T_COMPRESS';

 

  NUM_ROWS     BLOCKS COMPRESSION

---------- ---------- -----------

      1367         11 ENABLED

 

 

我们当创建数据表就指定compress选项,数据表创建后就是压缩属性的。相同的数据量,只分配了2个分区。下面看具体行的使用情况。

 

 

SQL> select dbms_rowid.rowid_relative_fno(rowid) fno, dbms_rowid.rowid_block_number(rowid) bno, count(*) from t_compress group by dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid) order by bno;

 

       FNO        BNO   COUNT(*)

---------- ---------- ----------

         4       4124        178

         4       4125        199

         4       4126        177

         4       4127        197

         4       4128        189

         4       4129        185

         4       4130        207

         4       4131         35

 

8 rows selected

 

 

具体行在块的分配上,只用到了8个数据块进行存储。平均每个数据块容纳数据行接近200行。

 

说明:当我们在创建数据表的时候,就指定了compress选项。那么直接进行CATS插入的时候,压缩功能开启。同时,压缩效果较优。

 

注意:我们这里面使用的是CATS方式插入数据,而不是日常OLTP方式。两种方式差异显著。

 

3、变化分配数据插入实验

 

CATS方式是一种“压实”的插入方式。如果我们在变化过程中改变了数据表的压缩选项,空间分配情况会如何呢?

 

我们首先准备一个数据表,非压缩状态下插入过一部分的数据。

 

--插入一部分数据;

SQL> create table t_sample as select * from t_source where mod(object_id,2)=0;

Table created

 

SQL> select count(*) from t_sample;

  COUNT(*)

----------

       695

 

SQL> exec dbms_stats.gather_table_stats(user,'T_SAMPLE',cascade => true);

PL/SQL procedure successfully completed

 

 

SQL> select HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS, EXTENTS from dba_segments where wner='SCOTT' and segment_name='T_SAMPLE';

HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS    EXTENTS

----------- ------------ ---------- ---------- ----------

          4         4139     131072         16          2

 

SQL>  select NUM_ROWS, BLOCKS, Compression from dba_tables where wner='SCOTT' and table_name='T_SAMPLE';

  NUM_ROWS     BLOCKS COMPRESSION

---------- ---------- -----------

       695         13 DISABLED

 

SQL> select dbms_rowid.rowid_relative_fno(rowid) fno, dbms_rowid.rowid_block_number(rowid) bno, count(*) from t_sample group by dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid) order by bno;

 

       FNO        BNO   COUNT(*)

---------- ---------- ----------

         4       4140         80

         4       4141         75

         4       4142         74

         4       4143         71

         4       4144         74

         4       4145         74

         4       4146         75

         4       4147         74

         4       4148         79

         4       4149         19

 

10 rows selected

 

 

分配情况和t_source的趋势相似。我们修改数据表属性。

 

 

SQL> alter table t_sample compress;

Table altered

 

SQL> exec dbms_stats.gather_table_stats(user,'T_SAMPLE',cascade => true);

PL/SQL procedure successfully completed

 

SQL> select HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS, EXTENTS from dba_segments where wner='SCOTT' and segment_name='T_SAMPLE';

 

HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS    EXTENTS

----------- ------------ ---------- ---------- ----------

          4         4139     131072         16          2

 

SQL> select NUM_ROWS, BLOCKS, Compression from dba_tables where wner='SCOTT' and table_name='T_SAMPLE';

 

  NUM_ROWS     BLOCKS COMPRESSION

---------- ---------- -----------

       695         13 ENABLED

 

SQL> select dbms_rowid.rowid_relative_fno(rowid) fno, dbms_rowid.rowid_block_number(rowid) bno, count(*) from t_sample group by dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid) order by bno;

 

       FNO        BNO   COUNT(*)

---------- ---------- ----------

         4       4140         80

         4       4141         75

         4       4142         74

         4       4143         71

         4       4144         74

         4       4145         74

         4       4146         75

         4       4147         74

         4       4148         79

         4       4149         19

10 rows selected

 

 

注意:此时我们修改了数据表属性,变化为compress。但是,现有数据并没有被压缩,而是保留为原有的情况。平均块容量为80左右个数据行,而非压缩下的上百行。

 

笔者此时猜想了一种可能,有没有在内部已经进行了空间重排,形成行链接模式。经过测试,发现没有行链接。而且在修改数据表compress属性的时候,执行时间也没有进行复杂变化的机会。

 

那么,我们接下来插入剩下的数据,使用OLTP方式。

 

 

SQL> insert into t_sample select * from t_source where mod(object_id,2)=1;

672 rows inserted

 

SQL> commit;

Commit complete

 

SQL> select count(*) from t_sample;

  COUNT(*)

----------

      1367

 

SQL> exec dbms_stats.gather_table_stats(user,'T_SAMPLE',cascade => true);

PL/SQL procedure successfully completed

 

SQL> select HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS, EXTENTS from dba_segments where wner='SCOTT' and segment_name='T_SAMPLE';

HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS    EXTENTS

----------- ------------ ---------- ---------- ----------

          4         4139     196608         24          3

 

SQL> select NUM_ROWS, BLOCKS, Compression from dba_tables where wner='SCOTT' and table_name='T_SAMPLE';

 

  NUM_ROWS     BLOCKS COMPRESSION

---------- ---------- -----------

      1367         23 ENABLED

 

SQL> select dbms_rowid.rowid_relative_fno(rowid) fno, dbms_rowid.rowid_block_number(rowid) bno, count(*) from t_sample group by dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid) order by bno;

 

       FNO        BNO   COUNT(*)

---------- ---------- ----------

         4       4140         80

         4       4141         75

         4       4142         74

         4       4143         71

         4       4144         74

         4       4145         74

         4       4146         75

         4       4147         74

         4       4148         79

         4       4149         19

         4       4150         74

         4       4151         78

         4       4152         75

         4       4162         74

         4       4163         75

         4       4164         77

         4       4165         69

         4       4167         72

         4       4168         78

 

19 rows selected

 

 

注意:此时虽然是压缩模式,但是使用OLTP insert方式后,数据表空间并没有节省!新分配空间,依然是使用非压缩方式——这点可以从块行容量上看出来。

 

解决方法——Move操作

 

解决的方法,我们可以采用move移动。Move是一种对数据表物理存储进行重排的过程,相当于在另一个磁盘上进行数据表重新组织,对应的空间乃至段头都要发生变化。Move是我们经常使用的降低HWM的方法。

 

 

SQL> alter table t_sample move;

Table altered

 

SQL> exec dbms_stats.gather_table_stats(user,'T_SAMPLE',cascade => true);

PL/SQL procedure successfully completed

 

SQL> select HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS, EXTENTS from dba_segments where wner='SCOTT' and segment_name='T_SAMPLE';

 

HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS    EXTENTS

----------- ------------ ---------- ---------- ----------

          4         4171     131072         16          2

 

SQL> select NUM_ROWS, BLOCKS, Compression from dba_tables where wner='SCOTT' and table_name='T_SAMPLE';

  NUM_ROWS     BLOCKS COMPRESSION

---------- ---------- -----------

      1367         11 ENABLED

 

SQL> select dbms_rowid.rowid_relative_fno(rowid) fno, dbms_rowid.rowid_block_number(rowid) bno, count(*) from t_sample group by dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid) order by bno;

 

       FNO        BNO   COUNT(*)

---------- ---------- ----------

         4       4172        173

         4       4173        173

         4       4174        170

         4       4175        179

         4       4176        173

         4       4177        166

         4       4178        182

         4       4179        151

 

8 rows selected

 

 

结论,我们发现空间被压缩,块行容量增加。

 

上面的实验,告诉我们几个结论:

 

ü        Compress是数据段的一个属性。当我们单纯进行compressnocompress切换的时候,数据已经分配空间是不会发生变化的;

ü        即使在compress的数据表,当我们进行常规OLTP数据插入的时候,是不会应用压缩选项的;

ü        Move操作通过重新促使系统进行数据空间分配的配比,可以应用实现compress的结果——注意是结果,数据表被压缩!

 

下面我们通过几个极端情况实验,继续分析10gR2Compression

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-719482/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
求道~

注册时间:2010-11-30

  • 博文量
    545
  • 访问量
    7545327