实验: ASSM内部存储研究大揭密

来源:互联网 发布:伊塞亚·托马斯数据 编辑:程序博客网 时间:2024/06/07 00:34

实验: ASSM内部存储研究大揭密


这篇文章转贴:http://www.itpub.net/thread-152489-1-1.html,其中的实验我从重做了一遍,对ASSM有了更深刻的了解。由于篇幅的原因没有将dump信息写出来。

 

    在9.2.0以前,表的剩余空间的管理与分配都是由连接列表freelist来完成的,因为freelist存在串行的问题,因此容易引起往往容易引起段头的争用与空间的浪费(其实这一点并不明显),最主要的还是因为需要DBA 花费大量的精力去管理这些争用并监控表的空间利用。

    自动段空间管理(ASSM),它首次出现在Oracle920里。有了ASSM,连接列表freelist被位图所取代,它是一个二进制的数组,能够迅速有效地管理存储扩展和剩余区块(free block),因此能够改善分段存储本质,ASSM表空间上创建的段还有另外一个称呼叫Bitmap Managed Segments(BMB 段)。

    让我们看看位图freelist是如何实现的。我会从使用区段空间管理自动参数创建tablespace开始:

create tablespace demo datafile '/oradata/ltest/demo01.dbf' size 50m

extent management local

segment space management auto;

    一旦你定义好了tablespace,那么表和索引就能够使用各种方法很容易地被移动到新的tablespace里,带有ASSM的本地管理tablespace会略掉任何为PCTUSED、NEXT和FREELISTS所指定的值。

    当表格或者索引被分配到这个tablespace以后,用于独立对象的PCTUSED的值会被忽略,而Oracle9i会使用位图数组来自动地管理tablespace里表格和索引的freelist。对于在LMT的tablespace内部创建的表格和索引而言,这个NEXT扩展子句是过时的,因为由本地管理的tablespace会管理它们。但是,INITIAL参数仍然是需要的,因为Oracle不可能提前知道初始表格加载的大小。对于ASSM而言,INITIAL最小的值是三个块。

    新的管理机制用位图来跟踪或管理每个分配到对象的块,每个块有多少剩余空间根据位图的状态来确定,如>75%,50%-75%,25%-50%和<25%,也就是说位图其实采用了四个状态位来代替以前的pctused,什么时候该利用该数据块则由设定的pctfree来确定。

    使用ASSM的一个巨大优势是,位图freelist肯定能够减轻缓冲区忙等待(buffer busy wait)的负担,这个问题在Oracle9i以前的版本里曾是一个严重的问题。

    在没有多个freelist的时候,每个Oracle表格和索引在表格的头部都曾有一个数据块,用来管理对象所使用的剩余区块,并为任何SQL插入声明所创建的新数据行提供数据块。当数据缓冲内的数据块由于被另一个DML事务处理锁定而无法使用的时候,缓冲区忙等待就会发生。当你需要将多个任务插入到同一个表格里的时候,这些任务就被强制等待,而同时Oracle会在同时分派剩余的区块,一次一个。

    有了ASSM之后,Oracle宣称显著地提高了DML并发操作的性能,因为(同一个)位图的不同部分可以被同时使用,这样就消除了寻找剩余空间的串行化。根据Oracle的测试结果,使用位图freelist会消除所有分段头部(对资源)的争夺,还能获得超快的并发插入操作。

    尽管ASSM显示出了令人激动的特性并能够简化Oracle DBA的工作,但是Oracle9i的位图分段管理还是有一些局限性的:

Ø  一旦DBA被分配之后,它就无法控制tablespace内部的独立表格和索引的存储行为。

Ø  你不能够使用ASSM创建临时的tablespace。这是由排序时临时分段的短暂特性所决定的。

Ø  只有本地管理的tablespace才能够使用位图分段管理。

Ø  使用超高容量的DML(例如INSERT、UPDATE和DELETE等)的时候可能会出现性能上的问题,但是在最新的版本上如9204以上,ASSM也开始了被广泛的应用。

1 实验过程

1.1 创建表空间

SQL> create tablespace demo datafile '/oradata/ltest/demo01.dbf' size 50m extent management local segment space management auto;

Tablespace created

1.2 创建表

SQL> create table demotab(x number) tablespace demo storage (initial 1000K);

Table created

SQL> select t.table_name,

  2         t.initial_extent / 1024 "INITIAL_EXTENT(K)",

  3         t.next_extent,

  4         t.pct_free,

  5         t.pct_used

  6    from user_tables t

  7   where t.table_name = 'DEMOTAB';

TABLE_NAME                     INITIAL_EXTENT(K) NEXT_EXTENT   PCT_FREE   PCT_USED

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

DEMOTAB                                     1000                     10

SQL> select t.segment_name, t.extent_id, t.bytes, t.blocks, t.block_id

  2    from dba_extents t

  3   where t.segment_name = 'DEMOTAB';

SEGMENT_NAME       EXTENT_ID      BYTES     BLOCKS   BLOCK_ID

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

DEMOTAB                    0      65536          8          9

DEMOTAB                    1      65536          8         17

DEMOTAB                    2      65536          8         25

DEMOTAB                    3      65536          8         33

DEMOTAB                    4      65536          8         41

DEMOTAB                    5      65536          8         49

DEMOTAB                    6      65536          8         57

DEMOTAB                    7      65536          8         65

DEMOTAB                    8      65536          8         73

DEMOTAB                    9      65536          8         81

DEMOTAB                   10      65536          8         89

DEMOTAB                   11      65536          8         97

DEMOTAB                   12      65536          8        105

DEMOTAB                   13      65536          8        113

DEMOTAB                   14      65536          8        121

DEMOTAB                   15      65536          8        129

16 rows selected

可以看到,NEXT_EXTENT与PCT_USED都为空。其中NEXT_EXTENT为空,这是因为ALLOCATION_TYPE是SYSTEM不是UNIFORM。

1.3 分析表的存储结构

SQL> exec show_space('DEMOTAB');

Total Blocks  ..........................128

Total Bytes   ..........................1048576

Total MBytes  ..........................1

Unused Blocks ..........................125

Unused Bytes  ..........................1024000

Unused KBytes ..........................1000

Used Blocks   ..........................3

Used Bytes    ..........................24576

Used KBytes   ..........................24

Last Used Ext FileId....................9

Last Used Ext BlockId...................9

Last Used Block.........................3

 

The segment is analyzed below

FS1 Blocks (0-25)   ....................0

FS2 Blocks (25-50)  ....................0

FS3 Blocks (50-75)  ....................0

FS4 Blocks (75-100) ....................0

Unformatted Blocks  ....................0

Full Blocks         ....................0

 

PL/SQL procedure successfully completed

1.4 dump数据块

SQL> alter system dump datafile 9 block 9;

System altered

SQL> alter system dump datafile 9 block 10;

System altered

SQL> alter system dump datafile 9 block 11;

System altered

从第9个块开始,文件头占用了64K的空间等于8个块。从dba_extents中也能看到这样的信息,实际上DEMOTAB这个段是从第9个块开始的。

问题?为什么这里只保留16个块的信息呢?这需要我们进一步研究(往下看)。

分析块10,叫SECOND LEVEL BITMAP BLOCK。这个就比较有意思了,记录了可能出现的类似于块9的块出现的地址(DBA)。刚才在上面不是说了吗,块9只能记录16个块的信息,那16个块之后的信息怎么办?BMB段采用了分布的策略,在第25个块的地方,oracle将增加一个新的块用来记录下16个块(等会儿看测试),那么块10记录的就是这些块的地址了,如:

0x06800019 Free: 5 Inst: 1 代表下一个块的地址是19(十六进制),其实是就是十进制的25。那么我们想象,再下一个是25 + 16 = 41。应当是十六进制的29,再查看块10的内容,大家可以知道这个块的作用了吧。

再看块11,是该表的段头,这里记录了表的区间地图,包括表段的16个区间的分布地址,如果没有创建表,是没有该块的,这个块与ASSM位图块本身没有多大关系,在每个段的头部都会有一个,因为这个是该表空间的第一个段,所以位置放在了块11。

可以看到其实在ASSM的表里面,取消了原来的freelist,其实增加了很多块来管理块的数据,这些块不再分布在块的头部,而是分布在表的内部,每隔16个块(这个数目与不同的环境可能有差别),就有一个块来记录下16个块的数据保留的情况。

位图数据的级别可以分为三个级别,当存在一个或多个一级位图块(如块9,19)的时候,将由二级位图(如块10)块来保存一级位图块的地址,同理,一个二级位图块不够使用而出现多个二级位图块的时候,将由三级位图块来保存二级位图块的地址(类似索引结构,由于三级位图块的出现需要很多数据块,所以这里不讨论三级位图块)。整个位图数组的结构形成一个树状结构,有利于ORACLE跟踪所有的位图数据块的位置。

1.5 插入数据后分析

SQL> insert into demotab select rownum from dba_objects;

50391 rows inserted

SQL> commit;

Commit complete

SQL> exec show_space('DEMOTAB');

Total Blocks  ..........................128

Total Bytes   ..........................1048576

Total MBytes  ..........................1

Unused Blocks ..........................40

Unused Bytes  ..........................327680

Unused KBytes ..........................320

Used Blocks   ..........................88

Used Bytes    ..........................720896

Used KBytes   ..........................704

Last Used Ext FileId....................9

Last Used Ext BlockId...................89

Last Used Block.........................8

 

The segment is analyzed below

FS1 Blocks (0-25)   ....................0

FS2 Blocks (25-50)  ....................0

FS3 Blocks (50-75)  ....................1

FS4 Blocks (75-100) ....................3

Unformatted Blocks  ....................0

Full Blocks         ....................76

 

PL/SQL procedure successfully completed

可以看到:

Total Blocks  ..........................128

Unused Blocks ..........................40

Used Blocks   ..........................88

就是说,这次插入用了88个块。

但是看下面的数据,也就是数据块只有1 + 3 + 76 = 80个,还有8个的差别在哪里呢?已知的就是段头有3个,那还有5个应当就是分布在表中的位图块了(假定)。将进一步分析。

用了88个块,其实就是11个区间,11个区间,每个位图块只能管理16个块(这一点在不同的环境和段大小的情况会有不同的),这里应当用到了6(88 / 16 取整后加1)个位图块才能够管理过来,6个中有一个属于段头3个块中的一个,那正好是80 + 3 + (6 -`1) = 88了。后面进一步分析。

2 dump位图块

从dump的信息可以看出:

二级位图块:10

一级位图块:9,25,41,57,73,89

段头块:11

2.1 分析二级位图块

……

   0x02400009  Free: 1 Inst: 1  --> 对应块9

   0x02400019  Free: 1 Inst: 1  --> 对应块25

   0x02400029  Free: 1 Inst: 1  --> 对应块41

   0x02400039  Free: 1 Inst: 1  --> 对应块57

   0x02400049  Free: 1 Inst: 1  --> 对应块71

   0x02400059  Free: 5 Inst: 1  --> 对应块89

   0x02400069  Free: 5 Inst: 1

   0x02400079  Free: 5 Inst: 1

……

2.2 分析一级位图块

块09:1个一级位图块 + 1个二级位图块 + 1个段头块 + 13个FULL块

块25:1个一级位图块 + 15个FULL块

块41:1个一级位图块 + 15个FULL块

块57:1个一级位图块 + 15个FULL块

块71:1个一级位图块 + 15个FULL块

块57:1个一级位图块 + 3个75-100% FREE块 + 1个50-75% FREE块 + 3个FULL块(还有8个是未格式化的)

结论是:

Blocks (50-75%)有1个,Blocks (75-100%)有3个,Full Blocks有76个。这个结果与用show_space存储过程算出来的是一样的。

2.3 分析段头块

在段头块11中:

……

  Low HighWater Mark :

      Highwater::  0x0240000c  ext#: 0      blk#: 3      ext size: 8    

  #blocks in seg. hdr's freelists: 0    

  #blocks below: 0    

  mapblk  0x00000000  offset: 0    

  Level 1 BMB for High HWM block: 0x02400059

  Level 1 BMB for Low HWM block: 0x02400009

……

结论:

1. 底的高水位点从12(十六进制的c)个块开始(前面是8个文件头 + 2个位图块 + 1个段头块)。

2. 一级位图块高的高水位点是89(十六进制的59),低水位点是9(十六进制的9)。

 

……

  Segment Type: 1 nl2: 1      blksz: 8192   fbsz: 0     

  L2 Array start offset:  0x00001434

  First Level 3 BMB:  0x00000000

  L2 Hint for inserts:  0x0240000a

  Last Level 1 BMB:  0x02400079

  Last Level II BMB:  0x0240000a

  Last Level III BMB:  0x00000000

     Map Header:: next  0x00000000  #extents: 16   obj#: 53313  flag: 0x10000000

  Inc # 0

  Extent Map

……

结论:从上面的信息可以看到最后使用的一级,二级,三级位图块的地址。

 

0 0
原创粉丝点击