oracle1新建库设置压缩功能,Oracle压缩效能小结1-压缩功能介绍

Oracle压缩功能小结1--压缩功能介绍

Oracle数据库的压缩功能

大家听到这个词,一定就想到了节省硬盘空间吧。没错,它就是用来干这个的,但是向外延伸一下,它不仅可以节省硬盘空间,更可以节省带宽以及内存的使用(cpu有一点点损耗因为需要更多的计算取值操作,但是鉴于大多数环境下cpu都有空闲,所以也可以忽略了)。

Basiccompression这个功能从9i开始就有提供,11gr1开始提供了新的压缩功能,即OLTP compression。Basic compression是包括在EE版本中的,不需要额外收费,但是OLTP compression则需要额外的Oracle Advanced Compression optionlicense。高级?想用?掏钱吧。

下面的图片能够帮助你简单了解压缩块的原理:

140758231.jpg

简单来说,就是在block中会存有特殊的数据结构,symbol table。

Symboltable dump出来的内容如下所示:

tab 0, row 0, @0x1da4

tl: 7 fb: --H-FL-- lb: 0x0 cc: 12

col 0:*NULL*

col 1: [5] 56 41 4c 49 44

col 2: [1] 4e

col 3:*NULL*

col 4: [1] 4e

col 5: [1] 4e

col 6: [3] 53 59 53

col 7: [7] 78 6f 0a 1e 0d 39 19

col 8:[19] 32 30 31 31 2d 31 30 2d 33 30 3a 3132 3a 35 36 3a 32 34

col 9: [2] c1 05

col 10: [ 5] 49 4e 44 45 58

col 11: [ 7] 78 6f 0a 1e 0d 39 19

bindmp: 00 2a 0c 15 20 24 22

真正的数据内容如下所示:

tab 0, row 0, @0x1da4

tl: 7 fb: --H-FL-- lb: 0x0 cc: 12

col 0:*NULL*

col 1: [5] 56 41 4c 49 44

col 2: [1] 4e

col 3:*NULL*

col 4: [1] 4e

col 5: [1] 4e

col 6: [3] 53 59 53

col 7: [7] 78 6f 0a 1e 0d 39 19

col 8:[19] 32 30 31 31 2d 31 30 2d 33 30 3a 3132 3a 35 36 3a 32 34

col 9: [2] c1 05

col 10: [ 5] 49 4e 44 45 58

col 11: [ 7] 78 6f 0a 1e 0d 39 19

bindmp: 00 2a 0c 15 20 24 22

有点类似于clustertable的block结构。简单来说就是只将block重复的内容存放一份到symbol table中,真正的表row

piece引用存放在symbol table中的重复的内容。因为Basiccompression和OLTPcompresssion都是块内压缩,所以就算拥有重复的内容,但是如果不在同一个块内存放,还是无法达到压缩的效果。其原理先介绍到这,如果想要深入研究,可以参考老熊的blog。

Oracle压缩表数据块格式解析:

http://www.laoxiong.net/dissect_compressed_block_part1.html

概念补完了,下面来简单介绍一下表压缩的几种类型:

1. 不压缩

别心急,我觉得它应该算是表压缩的类型之一,为了严谨一些,这里把它列为第一位。关键字nocompress。意思就是不压缩。默认创建表的时候会根据你的表空间的default属性来判断是否压缩。如果你的表空间定义为default compress,那么在此表空间创建非压缩表的时候则需要指定nocompress。例句:

create table t(id number) nocompress ;

相关SQL(留给大家自己测试):

alter tablespace users default compress ;

select tablespace_name , compress_for fromdba_tablespaces where tablespace_name='USERS' ;

create table ttt (id number) tablespace users ;

create table ttt2 (id number) tablespace users nocompress ;

select table_name , COMPRESS_FOR fromuser_tables where table_name in ('TTT','TTT2') ;

alter tablespace users default nocompress ;

select tablespace_name , compress_for fromdba_tablespaces where tablespace_name='USERS' ;

2. Basic compression

l  要点1:数据压缩只在directpath load的时候才会生效,对于普通的dml语句insert、update不会发生压缩。

l  要点2:压缩的时候为了保证最大程度的压缩,会自动设置pctfree为0(不是强制的,也可以在建表的时候设置pctfree为其他值)。

例句:

create table t(id number) compress ;

create table t(id number) compress basic ;

3. OLTP compression

l  要点1:不像Basic compression,OLTPcompression会对所有的dml生效,所以适用于OLTP系统。

l  要点2:自动设置pctfree为10,也可以自行设置。

l  要点3:oracle数据库内部的压缩动作不是在所有dml操作中都产生,只有当新的block中的数据存放到达了厥值的时候才会引发块内的压缩操作。

这里重点描述一下第三个要点:

oracle数据库压缩数据块在批量模式下,而不是每个更改数据的操作都会引发压缩操作。block中保留未压缩的数据达到了一个厥值的时候会引发块内的压缩操作。

当一个事务导致在block中的数据达到了厥值,所有的block中的内容就会被压缩。然后,更多的数据加入到块中,再一次达到厥值,整个block会重新压缩,以达到最大程度的压缩级别。这个过程会一直重复,直到oracle 数据库确定无法再从压缩上获得更高的效益。只有某些触发压缩条件的的事务会经历轻微的压缩开销。

所以多数oltp事务作用在压缩的块上面,会和未压缩的表上拥有相同的性能。只有那些比较倒霉的操作会引发块内的压缩动作。

这里的详细内容可以参考aco白皮书。

例句:

create table t(id number) compress for oltp ;

4. HCC(Hybrid Columnar Compression)

这个特性只为Exadata一体机环境下的Oracle数据库提供。可以分为4个级别,即:

l  Query low

l  Query high

l  Archive low

l  Archive high

比较适用于更改不频繁或者readonly的表。根据上面排列的级别,相应的压缩比越来越高,看到介绍,竟然最多可以达到30倍,确实令人咋舌(当然这应该是最好的情况)。

原理简单描述:

140758232.jpg

不像传统的数据存储,一行中所有的信息都存放在一起。而是使用CU(CompressionUnit)的结构来存储数据,将一组(很多行)行中每列的信息存放在一起,然后执行压缩操作。可以节省更多的空间。(原来只是块内引用,现在是多块内引用,肯定节省更多的空间)但是同样的,由于这种存储结构,在发生更新1行的数据的时候,会连带的锁定一个Logical

Compression Unit中的所有行。

我不是OracleDatabase的销售,所以关于HCC的内容就介绍到这里。最后说一下关于压缩的几点限制:

1.      Compress Basic和compress foroltp 不支持超过255列的信息。(真心蛋疼,难道是因为超过255列的row会跨越多个row piece的原因?)

2.      BasicFile LOBs 不支持压缩,SecureFileLOBs支持压缩。(新东西带来新bug)

3.      使用Compress Basic的时候无法dropcolumn,但是对于compress for oltp以及hcc中的各种压缩格式是允许的。

4.      不支持索引组织表。

5.      不支持外部表或者ClusterTable(直接说只支持堆积表得了)。

HCC的限制内容不描述了。

附件

附件1 show_space脚本

下面附上show_space(itpub改良版)脚本:

CREATE OR REPLACE PROCEDURE show_space(p_segname_1 IN VARCHAR2,

p_type_1 IN VARCHAR2 DEFAULT'TABLE',

p_space IN VARCHAR2 DEFAULT'AUTO',

p_analyzed IN VARCHAR2 DEFAULT'N',

p_partition_1 IN VARCHAR2 DEFAULT NULL,

p_owner_1 IN VARCHAR2 DEFAULTUSER)

AUTHIDCURRENT_USER AS

p_segname VARCHAR2(100);

p_type VARCHAR2(30);

p_owner VARCHAR2(30);

p_partition VARCHAR2(50);

l_unformatted_blocks NUMBER;

l_unformatted_bytes NUMBER;

l_fs1_blocks NUMBER;

l_fs1_bytes NUMBER;

l_fs2_blocks NUMBER;

l_fs2_bytes NUMBER;

l_fs3_blocks NUMBER;

l_fs3_bytes NUMBER;

l_fs4_blocks NUMBER;

l_fs4_bytes NUMBER;

l_full_blocks NUMBER;

l_full_bytes NUMBER;

l_free_blks NUMBER;

l_total_blocks NUMBER;

l_total_bytes NUMBER;

l_unused_blocks NUMBER;

l_unused_bytes NUMBER;

l_LastUsedExtFileId NUMBER;

l_LastUsedExtBlockId NUMBER;

l_LAST_USED_BLOCK NUMBER;

PROCEDURE p(p_label IN VARCHAR2, p_num IN NUMBER) IS

BEGIN

DBMS_OUTPUT.put_line(RPAD(p_label,40, '.') || p_num);

END;

BEGIN

p_segname := UPPER(p_segname_1);

p_owner := UPPER(p_owner_1);

p_type := p_type_1;

p_partition := UPPER(p_partition_1);

IF(p_type_1 = 'i' OR p_type_1 = 'I') THEN

p_type:= 'INDEX';

END IF;

IF(p_type_1 = 't' OR p_type_1 = 'T') THEN

p_type := 'TABLE';

END IF;

IF(p_type_1 = 'tp' OR p_type_1 = 'TP') THEN

p_type := 'TABLE PARTITION';

END IF;

IF(p_type_1 = 'ip' OR p_type_1 = 'IP') THEN

p_type := 'INDEX PARTITION';

END IF;

IF(p_type_1 = 'c' OR p_type_1 = 'C') THEN

p_type := 'CLUSTER';

END IF;

DBMS_SPACE.UNUSED_SPACE(segment_owner => p_owner,

segment_name => p_segname,

segment_type => p_type,

partition_name => p_partition,

total_blocks => l_total_blocks,

total_bytes => l_total_bytes,

unused_blocks => l_unused_blocks,

unused_bytes => l_unused_bytes,

LAST_USED_EXTENT_FILE_ID =>l_LastUsedExtFileId,

LAST_USED_EXTENT_BLOCK_ID =>l_LastUsedExtBlockId,

LAST_USED_BLOCK => l_LAST_USED_BLOCK);

IFp_space = 'MANUAL' OR (p_space <> 'auto' AND p_space <> 'AUTO')THEN

DBMS_SPACE.FREE_BLOCKS(segment_owner => p_owner,

segment_name => p_segname,

segment_type => p_type,

partition_name => p_partition,

freelist_group_id=> 0,

free_blks => l_free_blks);

p('Free Blocks', l_free_blks);

END IF;

p('Total Blocks', l_total_blocks);

p('Total Bytes', l_total_bytes);

p('Unused Blocks', l_unused_blocks);

p('Unused Bytes', l_unused_bytes);

p('LastUsed Ext FileId', l_LastUsedExtFileId);

p('LastUsed Ext BlockId', l_LastUsedExtBlockId);

p('LastUsed Block', l_LAST_USED_BLOCK);

/*IFthe segment is analyzed */

IFp_analyzed = 'Y' THEN

DBMS_SPACE.SPACE_USAGE(segment_owner => p_owner,

segment_name => p_segname,

segment_type => p_type,

partition_name => p_partition,

unformatted_blocks=> l_unformatted_blocks,

unformatted_bytes =>l_unformatted_bytes,

fs1_blocks => l_fs1_blocks,

fs1_bytes => l_fs1_bytes,

fs2_blocks => l_fs2_blocks,

fs2_bytes => l_fs2_bytes,

fs3_blocks => l_fs3_blocks,

fs3_bytes => l_fs3_bytes,

fs4_blocks => l_fs4_blocks,

fs4_bytes => l_fs4_bytes,

full_blocks => l_full_blocks,

full_bytes => l_full_bytes);

DBMS_OUTPUT.put_line(RPAD('', 50, '*'));

DBMS_OUTPUT.put_line('Thesegment is analyzed');

p('0%-- 25% free spaceblocks', l_fs1_blocks);

p('0%-- 25% free spacebytes', l_fs1_bytes);

p('25% -- 50% free spaceblocks', l_fs2_blocks);

p('25% -- 50% free spacebytes', l_fs2_bytes);

p('50% -- 75% free spaceblocks',l_fs3_blocks);

p('50% -- 75% free spacebytes', l_fs3_bytes);

p('75% -- 100% free spaceblocks', l_fs4_blocks);

p('75% -- 100% free spacebytes', l_fs4_bytes);

p('Unused Blocks', l_unformatted_blocks);

p('UnusedBytes', l_unformatted_bytes);

p('Total Blocks', l_full_blocks);

p('Total bytes', l_full_bytes);

END IF;

END;

使用方法:

_sys@FAKE> execdexter.show_space('BASICC3','T','AUTO','Y') ;

Total Blocks............................384

Total Bytes.............................3145728

Unused Blocks...........................18

Unused Bytes............................147456

Last Used Ext FileId....................4

Last Used Ext BlockId...................584704

Last Used Block.........................110

Thesegment is analyzed

0% -- 25% free spaceblocks..............0

0% -- 25% free spacebytes...............0

25% -- 50% free spaceblocks.............0

25% -- 50% free spacebytes..............0

50% -- 75% free spaceblocks.............0

50% -- 75% free spacebytes..............0

75% -- 100% free spaceblocks............43

75% -- 100% free spacebytes.............352256

Unused Blocks...........................0

Unused Bytes............................0

Total Blocks............................309

Total bytes.............................2531328

PL/SQL procedure successfully completed.

_sys@FAKE> exec dexter.show_space('BASICC2');

Total Blocks............................384

Total Bytes.............................3145728

Unused Blocks...........................54

Unused Bytes............................442368

Last Used Ext FileId....................4

Last Used Ext BlockId...................584320

Last Used Block.........................74

小脚本:

select table_name, compress_for, compression,PCT_FREE, PCT_USED

fromuser_tables

wheretable_name in ('BASICC', 'BASICC2');

注意,在创建compress压缩表的时候指定pct_free的值,不然结果不严谨。另外做测试的时候,大家可以放心使用

create table basicc2 tablespace users compressas select * from dba_objects ;

create table as select的方式创建压缩表,因为它本身使用的是direct pathwrite/read。

附件2 ACO 白皮书

aco白皮书下载地址:

http://download.csdn.net/detail/renfengjun/7514403

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值