2007年7月1日星期日

INSERT堆表时,数据块写入的顺序

读到《Expert one on one Oracle》表部分,TOM说,对于堆表数据的插入,数据会被写到最适合的块,而不是以特定的顺序写入。

进行了测试,了解了FREELIST的部分结构,虽然还有一个疑问,记录于此,以后再解决。表空间非ASSM。

SQL> show parameters db_block_size--8k大小的 block
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_block_size integer 8192

SQL> create table t ( i number, a varchar2(4000), b varchar2(4000) );
Table created.

SQL> select FILE_ID, block_id, blocks from dba_extents where segment_name = 'T'
AND OWNER = 'SCOTT';--找到这个表所对应SEGMETN的头,对于8k数据块来说,数据块是从第9个块开始的
FILE_ID BLOCK_ID BLOCKS
---------- ---------- ----------
12 9 8

SQL> alter system dump datafile 12 block 9;--dump segment header
System altered.

nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 0
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
End dump data blocks tsn: 13 file#: 12 minblk 9 maxblk 9
-- 根据nfl得知,有一个freelist,根据flag得知,这个freelist尚未使用

SQL> insert into t values ( 1, rpad('*',100,'*'), rpad('*',100,'*') );
1 row created.

SQL> SELECT ROWID, i, DBMS_ROWID.rowid_object (ROWID) OBJECT,
2 DBMS_ROWID.rowid_relative_fno (ROWID) file_no,
3 DBMS_ROWID.rowid_block_number (ROWID) BLOCK,
4 DBMS_ROWID.rowid_row_number (ROWID) rowno
5 FROM t;
ROWID I OBJECT FILE_NO BLOCK ROWNO
------------------ ---------- ---------- ---------- ---------- ----------
AAAHkEAAMAAAAAKAAA 1 30980 12 10 0

SQL> alter system dump datafile 12 block 10;--插入数据位于第10块,dump出来
System altered.

Block header dump: 0x0300000a
Object id on Block? Y
seg/obj: 0x7904 csc: 0x00.55c15a itc: 2 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
--根据flag得知,这个块在freelist上

SQL> alter system dump datafile 12 block 9;
System altered.

alter system dump datafile 12 block 9;
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 1
SEG LST:: flg: USED lhd: 0x0300000a ltl: 0x0300000a
End dump data blocks tsn: 13 file#: 12 minblk 9 maxblk 9
--顺便看一下block9, flg标示已经变为USED, lhd的值指向block 10的

SQL> insert into t values ( 2, rpad('*',3900,'1'), rpad('*',3900,'1') );
1 row created.

SQL> SELECT ROWID, i, DBMS_ROWID.rowid_object (ROWID) OBJECT,
2 DBMS_ROWID.rowid_relative_fno (ROWID) file_no,
3 DBMS_ROWID.rowid_block_number (ROWID) BLOCK,
4 DBMS_ROWID.rowid_row_number (ROWID) rowno
5 FROM t;
ROWID I OBJECT FILE_NO BLOCK ROWNO
------------------ ---------- ---------- ---------- ---------- ----------
AAAHkEAAMAAAAAKAAA 1 30980 12 10 0
AAAHkEAAMAAAAALAAA 2 30980 12 11 0

SQL> alter system dump datafile 12 block 10;
System altered.

alter system dump datafile 12 block 10;
Block header dump: 0x0300000a
Object id on Block? Y
seg/obj: 0x7904 csc: 0x00.55c15a itc: 2 flg: - typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
--flg的值为"-",表示当插入第二行的时候,block10已经从freelist中移掉。 为什么???block10有超过 8k*pctfree的空间啊?

SQL> alter system dump datafile 12 block 11;
System altered.
Block header dump: 0x0300000b
Object id on Block? Y
seg/obj: 0x7904 csc: 0x00.55c5b5 itc: 2 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
--block11这个时候已经加入freelist


结论:如果不是assm类型表空间,存在这种可能block不能被插入一个新的数据的时候将从 freelist中摘掉了

后续问题: oracle根据什么算法,将block10丛freelist移除? 不应该啊,因为block10有超过 8k*pctfree的空间。

参考:
在itpub的求助贴
Oracle Freelist和HWM原理及性能优化


没有评论: