原文链接:http://www.linuxidc.com/Linux/2011-07/38018p2.htm
(转载,自己备用)
二. ASSM 说明
在Orale 9i以前,表的剩余空间的管理与分配都是由链接列表freelist来完成的,因为freelist存在串行的问题因此容易引起往往容易引起段头的争用与空间的浪费(其实这一点并不明显),最主要的还是因为需要DBA 花费大量的精力去管理这些争用并监控表的空间利用。
自动段空间管理(ASSM),它首次出现在Oracle 920里。有了ASSM,链接列表freelist被位图所取代,它是一个二进制的数组,能够迅速有效地管理存储扩展和剩余区块(free block),因此能够改善分段存储本质,ASSM表空间上创建的段还有另外一个称呼叫Bitmap Managed Segments(BMB 段)。
让我们看看位图freelist是如何实现的。从使用区段空间管理自动参数创建tablespace开始:
create tablespace demo
datafile ''/ora01/oem/demo01.dbf ''
size 5m
EXTENT MANAGEMENT LOCAL -- Turn on LMT
SEGMENT SPACE MANAGEMENT AUTO -- Turn on ASSM;
一旦你定义好了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的位图分段管理还是有一些局限性的:
1. 一旦DBA被分配之后,它就无法控制tablespace内部的独立表格和索引的存储行为。
2. 大型对象不能够使用ASSM,而且必须为包含有LOB数据类型的表格创建分离的tablespace。
3. 你不能够使用ASSM创建临时的tablespace。这是由排序时临时分段的短暂特性所决定的。
4. 只有本地管理的tablespace才能够使用位图分段管理。
5· 使用超高容量的DML(例如INSERT、UPDATE和DELETE等)的时候可能会出现性能上的问题。
三. 相关测试:
1、我们先创建一个本地管理的表空间,采用段自动管理方式
/* Formatted on 2009-12-7 19:17:33 (QP5 v5.115.810.9015) */
CREATE TABLESPACE demo
DATAFILE ''D:/demo01.dbf''
SIZE 50M
EXTENT MANAGEMENT LOCAL --一定是本地管理
SEGMENT SPACE MANAGEMENT AUTO; --ASSM管理的标志
2、创建同样一个表
/* Formatted on 2009-12-7 19:18:00 (QP5 v5.115.810.9015) */
CREATE TABLE demotab (x NUMBER)
TABLESPACE demo
STORAGE (INITIAL 1000 K);
我们指定初试区间大小是1000K
/* Formatted on 2009-12-7 19:18:37 (QP5 v5.115.810.9015) */
SELECT t.table_name,
t.initial_extent,
t.next_extent,
t.pct_free,
t.pct_used
FROM user_tables t
WHERE t.table_name = ''DEMOTAB'';
TABLE_NAME INITIAL_EXTENT NEXT_EXTENT PCT_FREE PCT_USED
----------------------- -------------- --------------- ---------------- -------------------
DEMOTAB 1024000 10
可以看到,NEXT_EXTENT与PCT_USED都为空。
3、执行该过程,检查表的初始状态
exec show_space(''demotab'',''auto'',''T'',''Y''); --show_space() 代码见附件
Total Blocks............................128
Total Bytes.............................1048576
Unused Blocks...........................125
Unused Bytes............................1024000
Last Used Ext FileId....................7
Last Used Ext BlockId...................9
Last Used Block.........................3
*************************************************
The segment is analyzed
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............0
25% -- 50% free space bytes.............0
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................0
Total bytes.............................0
从这里我们能看到一些该表的特性,其中最引人注意的就是表头了,占用了三个块的大小(128-125)
另外一个注意的地方就是该表从第9个块开始,文件头占用了64K的空间等于8个块。
我们从dba_extent中也能看到这样的信息,是从第9个块开始的。
/* Formatted on 2009-12-7 19:24:23 (QP5 v5.115.810.9015) */
SELECT t.segment_name, t.extent_id, t.block_id
FROM dba_extents t
WHERE t.segment_name = ''DEMOTAB'';
SEGMENT_NAME EXTENT_ID BLOCK_ID
--------------- ---------- ----------
DEMOTAB 0 9
DEMOTAB 1 17
DEMOTAB 2 25
DEMOTAB 3 33
DEMOTAB 4 41
DEMOTAB 5 49
DEMOTAB 6 57
DEMOTAB 7 65
DEMOTAB 8 73
DEMOTAB 9 81
DEMOTAB 10 89
DEMOTAB 11 97
DEMOTAB 12 105
DEMOTAB 13 113
DEMOTAB 14 121
DEMOTAB 15 129
从这里可以看到,第一个区间的开始块是9
4、我直接开始分析第9,10,11个块(段头)
SQL> alter system dump datafile 7 block 9;
System altered
SQL> alter system dump datafile 7 block 10;
System altered
SQL> alter system dump datafile 7 block 11;
System altered
进入Udump 查看刚才生成的trace 文件
*** 2009-12-07 19:30:16.406
*** SERVICE NAME:(DBA.ANQINGREN.ORG) 2009-12-07 19:30:16.390
*** SESSION ID:(123.758) 2009-12-07 19:30:16.390
Start dump data blocks tsn: 8 file#: 7 minblk 9 maxblk 9
buffer tsn: 8 rdba: 0x01c00009 (7/9)
scn: 0x0000.001a0da0 seq: 0x01 flg: 0x04 tail: 0x0da02001
frmt: 0x02 chkval: 0x44e6 type: 0x20=FIRST LEVEL BITMAP BLOCK
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x085C8400 to 0x085CA400
85C8400 0000A220 01C00009 001A0DA0 04010000 [ ...............]
85C8410 000044E6 00000000 00000000 00000000 [.D..............]
85C8420 00000000 00000000 00000000 00000000 [................]
Repeat 1 times
85C8440 00000000 00000000 00000000 00000004 [................]
85C8450 FFFFFFFF 0000000D 00000003 00000010 [................]
85C8460 00010002 00000000 00000000 00000000 [................]
85C8470 00000000 00000003 00000000 00000000 [................]
85C8480 00000000 00000000 00000000 00000000 [................]
85C8490 01C0000A 00000000 00000000 00000003 [................]
85C84A0 00000008 01C0000C 00000000 00000000 [................]
85C84B0 00000000 00000000 00000000 00000001 [................]
85C84C0 0000D302 00000000 00000000 01C00009 [................]
85C84D0 00000008 00000000 01C00011 00000008 [................]
85C84E0 00000008 00000000 00000000 00000000 [................]
85C84F0 00000000 00000000 00000000 00000000 [................]
Repeat 8 times
85C8580 00000000 00000000 00000000 00001011 [................]
85C8590 00000000 00000000 00000000 00000000 [................]
Repeat 485 times
85CA3F0 00000000 00000000 00000000 0DA02001 [............. ..]
Dump of First Level Bitmap Block
--------------------------------
nbits : 4 nranges: 2 parent dba: 0x01c0000a poffset: 0
unformatted: 13 total: 16 first useful block: 3
owning instance : 1
instance ownership changed at
Last successful Search
Freeness Status: nf1 0 nf2 0 nf3 0 nf4 0
Extent Map Block Offset: 4294967295
First free datablock : 3
Bitmap block lock opcode 0
Locker xid: : 0x0000.000.00000000
Inc #: 0 Objd: 54018
HWM Flag: HWM Set
Highwater:: 0x01c0000c ext#: 0 blk#: 3 ext size: 8
#blocks in seg. hdr''s freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
--------------------------------------------------------
DBA Ranges :
--------------------------------------------------------
0x01c00009 Length: 8 Offset: 0
0x01c00011 Length: 8 Offset: 8
0:Metadata 1:Metadata 2:Metadata 3:unformatted
4:unformatted 5:unformatted 6:unformatted 7:unformatted
8:unformatted 9:unformatted 10:unformatted 11:unformatted
12:unformatted 13:unformatted 14:unformatted 15:unformatted
--------------------------------------------------------
End dump data blocks tsn: 8 file#: 7 minblk 9 maxblk 9
*** 2009-12-07 19:35:44.296
Start dump data blocks tsn: 8 file#: 7 minblk 10 maxblk 10
buffer tsn: 8 rdba: 0x01c0000a (7/10)
scn: 0x0000.001a0dc1 seq: 0x01 flg: 0x04 tail: 0x0dc12101
frmt: 0x02 chkval: 0x5439 type: 0x21=SECOND LEVEL BITMAP BLOCK
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x085C8400 to 0x085CA400
85C8400 0000A221 01C0000A 001A0DC1 04010000 [!...............]
85C8410 00005439 00000000 00000000 00000000 [9T..............]
85C8420 00000000 00000000 00000000 00000000 [................]
Repeat 1 times
85C8440 00000000 00000000 00000000 01C0000B [................]
85C8450 00000008 00000008 00000000 00000000 [................]
85C8460 00000000 00000000 0000D302 00000001 [................]
85C8470 00000000 01C00009 00010005 01C00019 [................]
85C8480 00010005 01C00029 00010005 01C00039 [....).......9...]
85C8490 00010005 01C00049 00010005 01C00059 [....I.......Y...]
85C84A0 00010005 01C00069 00010005 01C00079 [....i.......y...]
85C84B0 00010005 00000000 00000000 00000000 [................]
85C84C0 00000000 00000000 00000000 00000000 [................]
Repeat 498 times
85CA3F0 00000000 00000000 00000000 0DC12101 [.............!..]
Dump of Second Level Bitmap Block
number: 8 nfree: 8 ffree: 0 pdba: 0x01c0000b
Inc #: 0 Objd: 54018
opcode:0
xid:
L1 Ranges :
--------------------------------------------------------
0x01c00009 Free: 5 Inst: 1
0x01c00019 Free: 5 Inst: 1
0x01c00029 Free: 5 Inst: 1
0x01c00039 Free: 5 Inst: 1
0x01c00049 Free: 5 Inst: 1
0x01c00059 Free: 5 Inst: 1
0x01c00069 Free: 5 Inst: 1
0x01c00079 Free: 5 Inst: 1
--------------------------------------------------------
End dump data blocks tsn: 8 file#: 7 minblk 10 maxblk 10
Start dump data blocks tsn: 8 file#: 7 minblk 11 maxblk 11
buffer tsn: 8 rdba: 0x01c0000b (7/11)
scn: 0x0000.001a0dc6 seq: 0x01 flg: 0x04 tail: 0x0dc62301
frmt: 0x02 chkval: 0x79ad type: 0x23=PAGETABLE SEGMENT HEADER
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x085C8400 to 0x085CA400
85C8400 0000A223 01C0000B 001A0DC6 04010000 [#...............]
85C8410 000079AD 00000000 00000000 00000000 [.y..............]
85C8420 00000000 00000010 00000080 00000A9C [................]
85C8430 00000000 00000003 00000008 01C0000C [................]
85C8440 00000000 00000000 00000000 00000000 [................]
Repeat 1 times
85C8460 00000003 00000008 01C0000C 00000000 [................]
85C8470 00000000 00000000 00000000 01C00009 [................]
85C8480 01C00009 00000000 00000000 00000000 [................]
85C8490 00000000 00000000 00000000 00000000 [................]
Repeat 3 times
85C84D0 00000001 00002000 00000000 00001434 [..... ......4...]
85C84E0 00000000 01C0000A 00000001 01C00079 [............y...]
85C84F0 01C0000A 00000000 00000000 00000000 [................]
85C8500 00000000 00000000 00000010 00000000 [................]
85C8510 0000D302 10000000 01C00009 00000008 [................]
85C8520 01C00011 00000008 01C00019 00000008 [................]
85C8530 01C00021 00000008 01C00029 00000008 [!.......).......]
85C8540 01C00031 00000008 01C00039 00000008 [1.......9.......]
85C8550 01C00041 00000008 01C00049 00000008 [A.......I.......]
85C8560 01C00051 00000008 01C00059 00000008 [Q.......Y.......]
85C8570 01C00061 00000008 01C00069 00000008 [a.......i.......]
85C8580 01C00071 00000008 01C00079 00000008 [q.......y.......]
85C8590 01C00081 00000008 00000000 00000000 [................]
85C85A0 00000000 00000000 00000000 00000000 [................]
Repeat 144 times
85C8EB0 01C00009 01C0000C 01C00009 01C00011 [................]
85C8EC0 01C00019 01C0001A 01C00019 01C00021 [............!...]
85C8ED0 01C00029 01C0002A 01C00029 01C00031 [)...*...)...1...]
85C8EE0 01C00039 01C0003A 01C00039 01C00041 [9...:...9...A...]
85C8EF0 01C00049 01C0004A 01C00049 01C00051 [I...J...I...Q...]
85C8F00 01C00059 01C0005A 01C00059 01C00061 [Y...Z...Y...a...]
85C8F10 01C00069 01C0006A 01C00069 01C00071 [i...j...i...q...]
85C8F20 01C00079 01C0007A 01C00079 01C00081 [y...z...y.......]
85C8F30 00000000 00000000 00000000 00000000 [................]
Repeat 144 times
85C9840 00000000 00000000 01C0000A 00000000 [................]
85C9850 00000000 00000000 00000000 00000000 [................]
Repeat 185 times
85CA3F0 00000000 00000000 00000000 0DC62301 [.............#..]
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 16 #blocks: 128
last map 0x00000000 #maps: 0 offset: 2716
Highwater:: 0x01c0000c ext#: 0 blk#: 3 ext size: 8
#blocks in seg. hdr''s freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Unlocked
--------------------------------------------------------
Low HighWater Mark :
Highwater:: 0x01c0000c 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: 0x01c00009
Level 1 BMB for Low HWM block: 0x01c00009
--------------------------------------------------------
Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
L2 Array start offset: 0x00001434
First Level 3 BMB: 0x00000000
L2 Hint for inserts: 0x01c0000a
Last Level 1 BMB: 0x01c00079
Last Level II BMB: 0x01c0000a
Last Level III BMB: 0x00000000
Map Header:: next 0x00000000 #extents: 16 obj#: 54018 flag: 0x10000000
Inc # 0
Extent Map
-----------------------------------------------------------------
0x01c00009 length: 8
0x01c00011 length: 8
0x01c00019 length: 8
0x01c00021 length: 8
0x01c00029 length: 8
0x01c00031 length: 8
0x01c00039 length: 8
0x01c00041 length: 8
0x01c00049 length: 8
0x01c00051 length: 8
0x01c00059 length: 8
0x01c00061 length: 8
0x01c00069 length: 8
0x01c00071 length: 8
0x01c00079 length: 8
0x01c00081 length: 8
Auxillary Map
--------------------------------------------------------
Extent 0 : L1 dba: 0x01c00009 Data dba: 0x01c0000c
Extent 1 : L1 dba: 0x01c00009 Data dba: 0x01c00011
Extent 2 : L1 dba: 0x01c00019 Data dba: 0x01c0001a
Extent 3 : L1 dba: 0x01c00019 Data dba: 0x01c00021
Extent 4 : L1 dba: 0x01c00029 Data dba: 0x01c0002a
Extent 5 : L1 dba: 0x01c00029 Data dba: 0x01c00031
Extent 6 : L1 dba: 0x01c00039 Data dba: 0x01c0003a
Extent 7 : L1 dba: 0x01c00039 Data dba: 0x01c00041
Extent 8 : L1 dba: 0x01c00049 Data dba: 0x01c0004a
Extent 9 : L1 dba: 0x01c00049 Data dba: 0x01c00051
Extent 10 : L1 dba: 0x01c00059 Data dba: 0x01c0005a
Extent 11 : L1 dba: 0x01c00059 Data dba: 0x01c00061
Extent 12 : L1 dba: 0x01c00069 Data dba: 0x01c0006a
Extent 13 : L1 dba: 0x01c00069 Data dba: 0x01c00071
Extent 14 : L1 dba: 0x01c00079 Data dba: 0x01c0007a
Extent 15 : L1 dba: 0x01c00079 Data dba: 0x01c00081
--------------------------------------------------------
Second Level Bitmap block DBAs
--------------------------------------------------------
DBA 1: 0x01c0000a
End dump data blocks tsn: 8 file#: 7 minblk 11 maxblk 11
附件:Show_space() 存储过程代码:
CREATE OR REPLACE PROCEDURE show_space (p_segname_1 IN varchar2,
p_space IN varchar2 DEFAULT ''MANUAL'',
p_type_1 IN varchar2 DEFAULT ''TABLE'',
p_analyzed IN varchar2 DEFAULT ''N'' ,
p_owner_1 IN varchar2 DEFAULT USER
)
AS
p_segname VARCHAR2 (100);
p_type VARCHAR2 (10);
p_owner VARCHAR2 (30);
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); -- rainy changed
p_owner := UPPER (p_owner_1);
p_type := p_type_1;
IF (p_type_1 = ''i'' OR p_type_1 = ''I'')
THEN --rainy changed
p_type := ''INDEX'';
END IF;
IF (p_type_1 = ''t'' OR p_type_1 = ''T'')
THEN --rainy changed
p_type := ''TABLE'';
END IF;
IF (p_type_1 = ''c'' OR p_type_1 = ''C'')
THEN --rainy changed
p_type := ''CLUSTER'';
END IF;
DBMS_SPACE.unused_space (segment_owner => p_owner,
segment_name => p_segname,
segment_type => p_type,
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
);
IF p_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,
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 (''Last Used Ext FileId'', l_lastusedextfileid);
p (''Last Used Ext BlockId'', l_lastusedextblockid);
p (''Last Used Block'', l_last_used_block);
/*IF the segment is analyzed */
IF p_analyzed = ''Y''
THEN
DBMS_SPACE.space_usage (segment_owner => p_owner,
segment_name => p_segname,
segment_type => p_type,
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 (''The segment is analyzed'');
p (''0% -- 25% free space blocks'', l_fs1_blocks);
p (''0% -- 25% free space bytes'', l_fs1_bytes);
p (''25% -- 50% free space blocks'', l_fs2_blocks);
p (''25% -- 50% free space bytes'', l_fs2_bytes);
p (''50% -- 75% free space blocks'', l_fs3_blocks);
p (''50% -- 75% free space bytes'', l_fs3_bytes);
p (''75% -- 100% free space blocks'', l_fs4_blocks);
p (''75% -- 100% free space bytes'', l_fs4_bytes);
p (''Unused Blocks'', l_unformatted_blocks);
p (''Unused Bytes'', l_unformatted_bytes);
p (''Total Blocks'', l_full_blocks);
p (''Total bytes'', l_full_bytes);
END IF;
END;
exec show_space(''abc'',''auto'',''T'',''Y'');