Phone:18180207355 提供专业Oracle&MySQL数据恢复、性能优化、迁移升级、紧急救援等服务

昨天朋友问到压缩表的细节问题,我准备用实验来解释,最近很久也没写博客了,就正好完善一下,贴出来。

首先我们来看下10g的表压缩:

可以看到基本上没有差别,实际上压缩表和普通表在insert和delete上,基本上没啥区别(可能与细微差别,压缩表性能适当低一点).
那么update 呢? 其实,主要是体现在update上,为什么呢 ?

我们可以看到,其实压缩表和普通表一个不同之处在于其pctfree属性的差别。 针对压缩表,其pct属性是0,那么这样就很可能会导致
update时出现行迁移/行链接,这样也就必然会导致操作时代价变得更大,下面我来实验一下。

可以看到,普遍表update只需要7s,而压缩表update花了32s左右,是其4倍多. 而普通版update产生的redo
size是:15543172  ,压缩表产生的redo size是:13332484  在redo 大小上,差别不大。

在11g中,oracle引入了advanced compress特性,其实是在原来10g的压缩上更进一步了,可以实现OLTP类型压缩。

这么说明下,其实10g版本中的压缩表本身是为DSS类应用设计的,对于OLTP应用并不适用,另外就是其压缩数据的话,
限制比较多,对于普通的dml操作都是无法进行压缩的,只满足如下几种情况:

1. 使用sql*loader direct path加载.
2. 使用create table as select 方式操作.
3. 使用parallel insert操作.
4. 使用append hint.

在11g中,普通的dml操作也是可以压缩的,不管是单行操作,还是bulk 操作,均可压缩. 另外还提供了表空间级别的压缩.
表空间压缩是指,创建表空间时,就创建compress表空间,随后所有创建在该表空间的表都要被自动压缩.

鉴于11g新的特性,那么在11g的文档中,针对以前老的方式定义为basic compression,11g本身的压缩定义为OLTP compression.

另外11.2中,还引入了混合列压缩,不过该特性只能在oracle exadata上使用. 而OLTP compression则适用于OLTP和DSS。

下面我们再来演示下11g的OLTP compression.

可以看到,在11g中,oltp compression似乎比较成熟了,基本上跟普通版相当了。 至于basic compression和oltp compression,
总的来说,差不多。差别主要在update上。

最后我们再来看下10g中压缩表 block的结构:

我们block中存的数据是345-298=47 也正是tab0中所引用的条数。
tab 0, row 0, @0x1e88
tl: 9 fb: –H-FL– lb: 0x0  cc: 6
col  0: *NULL*
col  1: [ 5]  56 41 4c 49 44
col  2: [ 1]  4e
col  3: [ 1]  4e
col  4: [ 1]  4e
col  5: [ 3]  53 59 53
bindmp: 00 03 06 ff 2d 2e 2e 2e 29
00 03 表示引用次数
06    表示列数目
ff    即为255,表示null值,这个位置是第一位,就表示col 0这一列。
2d    表示引用的第45行
后面的2e 2e 2e 29 分别表示引用了第46行数据引用了3次,引用第29行数据,引用了1次。

来看第2行的bindmp信息:
bindmp: 00 03 08 00 2c db 32 30 31 30 2d 30 34 2d 31 35 3a 31 33 3a 31 34 3a 34 34

00 03  表示被引用了3次
08     表示一共8个列
00     如果小于等于200表示行号,这是0,即是第0行。
2c     转换为10进制是44,表示引用的第44行
db     转换后是219,大于200,表示表示后面的是一列数据,其长度=219-200

32~34  这19个bytes,就是后面的一列数据。

我们可以来看下这一列数据的含义:

SQL> select hextostr(’32 30 31 30 2d 30 34 2d 31 35 3a 31 33 3a 31 34 3a 34 34′) from dual;

HEXTOSTR(‘323031302D30342D31353A31333A31343A3434’)
———————————————————————————————-
2010-04-15:13:14:44

我们最后再来看下最后一行数据的情况;

bindmp: 2c 00 04 0a 12 cb c2 04 0c 15 cb c2 04 0c

2c 00  表示被引用的次数。 即这行数据被应用了44次。
04     表示被引用列的列数目,即一共4个列。即有4个列被引用
0a     转换后为10,表示引用的第10行
12     表示引用的第18行
cb     转换后为203,大于200,那么减去200后等于3,表示列的长度是3,即c2 04 0c

tab 0就是压缩表特定的格式,展示的是其引用关系。 下面的tab1就是实际的block内数据。

这里以倒数第2行来举例说明:

tab 1, row 296, @0x306
tl: 30 fb: –H-FL– lb: 0x0  cc: 13
col  0: *NULL*
col  1: [ 5]  56 41 4c 49 44
col  2: [ 1]  4e
col  3: [ 1]  4e
col  4: [ 1]  4e
col  5: [ 3]  53 59 53
col  6: [ 7]  78 6e 04 0f 0e 0f 2f
col  7: [19]  32 30 31 30 2d 30 34 2d 31 35 3a 31 33 3a 31 34 3a 34 36
col  8: [ 5]  49 4e 44 45 58
col  9: [ 7]  78 6e 04 0f 0e 0f 2f
col 10: [ 3]  c2 04 0b
col 11: [16]  49 5f 44 45 46 53 55 42 50 41 52 54 4c 4f 42 24
col 12: [ 3]  c2 04 0b
bindmp: 2c 00 04 0a 10 cb c2 04 0b d8 49 5f 44 45 46 53 55 42 50 41 52 54 4c 4f 42 24 cb c2 04 0b

从上面看,我们知道该压缩表有13个列。

我们直接看bindmp数据:

2c    表示行头
00    表示itl槽位,我这里是0.
04    表示被压缩后的列数目,即原来13个列,被压缩后变成4个列了。
0a    表示被压缩的列的个数  转换后为10,即有10个列被压缩
10    表示对应列编号,即第10个列,从上看,其长度为3
cb    转换后是203,减去200,表示后面列长度3,后面对应的数据为:c2 04 0b
d8    转换后为216,鉴于200,表示对应的列长度是16,即其对应的数据是:c2 04 0b d8 49 5f 44 45 46 53 55 42 50 41 52 54 4c 4f 42 24
cb    转换后是203,减去200,表示后面列长度3,后面对应的数据为:c2 04 0b

关于压缩表的block结构,老熊的博客中有2篇文章描述的比较详细,大家可以参考下,熊哥是这方面的权威。

最后简单总结下:

1. 10g版本中的压缩表(实际上是9iR2引入) 的block结构跟普遍表block结构没什么差别,可以简单的理解为是block内压缩,并
实现列级别共享。block内包含2个tab信息,其中一个是符号表(重复数据,被压缩的行),另外一个tab 1是实际的data数据.
tab 0中被压缩的列都有一个bindmp指针,指向tab1中的位置。

2. 11g版本中引入了oltp compression和tablespace compression,经过测试,至少在11.2版本中oltp compression还是比较
成熟了,不过对于实际应用,还是建议进行测试,以免碰到相关bug.

3. 10g 版本中的压缩表主要适用于dss应用,而11g的oltp compression特性,显然是为了适应oltp业务而产生的。

4. 压缩表在查询上,比普通表存在优势,可以降低逻辑读等资源的消耗,甚至memory等资源.

 

    分享到:
18180207355
加Q咨询