在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是数据段的一个属性。当我们单纯进行compress和nocompress切换的时候,数据已经分配空间是不会发生变化的;
ü 即使在compress的数据表,当我们进行常规OLTP数据插入的时候,是不会应用压缩选项的;
ü Move操作通过重新促使系统进行数据空间分配的配比,可以应用实现compress的结果——注意是结果,数据表被压缩!
下面我们通过几个极端情况实验,继续分析10gR2的Compression。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/17203031/viewspace-719482/ ,如需转载,请注明出处,否则将追究法律责任。