关于索引块空间的重用

    在oracle document中所说的索引块要等所有数据完全删除后才可重用,这是站在块的重新分配的角度上说的,也就是说,相当于索引块的 pctused=0 ,要完全删除后才回到 freelist(assm不存在freelist而是用bitmap来表示),但其实在索引块的内部,并不是说被删除的空间就不能被重用。所谓重用 的观点应该针对block来说而不应该针对row所在的位置,只要key value 落在该block可接受的范围内都可以重用,而不必关心是否完全相同。对于block里面的记录来说,物理位置并不是跟key顺序有关,可能由于 delete/update 等而发身变化

    测试如下

SQL> create table t as select * from dba_objects where object_id is not null;

表已创建。

SQL> create index t_index on t(object_id);

索引已创建。
SQL> desc t
名称 是否为空? 类型
----------------------------------------- -------- ----------------------------
OWNER VARCHAR2(30)
OBJECT_NAME VARCHAR2(128)
SUBOBJECT_NAME VARCHAR2(30)
OBJECT_ID NUMBER
DATA_OBJECT_ID NUMBER
OBJECT_TYPE VARCHAR2(18)
CREATED DATE
LAST_DDL_TIME DATE
TIMESTAMP VARCHAR2(19)
STATUS VARCHAR2(7)
TEMPORARY VARCHAR2(1)
GENERATED VARCHAR2(1)
SECONDARY VARCHAR2(1)


SQL> select FILE_ID,EXTENT_ID,BLOCK_ID from dba_extents where segment_name = 'T_INDEX';

FILE_ID EXTENT_ID BLOCK_ID
---------- ---------- ----------
9 0 569
9 1 577
9 2 585
9 3 593
9 4 601
9 5 609
9 6 617
9 7 625
9 8 633
9 9 641

已选择10行。

SQL> select min(object_id) from t;

MIN(OBJECT_ID)
--------------
2
由于是ASSM 类型的表空间,我通过其他方式找到索引叶子节点的开始位置为 block_id 573


SQL> alter system dump datafile 9 block 573;

kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8036
row#0[8024] flag: -----, lock: 0 8024表示block中的偏移bytes,也就是位置
col 0; len 2; (2): c1 03 --------这个值是2
col 1; len 6; (6): 02 40 00 6d 00 1f
row#1[8012] flag: -----, lock: 0
col 0; len 2; (2): c1 04
col 1; len 6; (6): 02 40 02 2f 00 26
row#2[8000] flag: -----, lock: 0
col 0; len 2; (2): c1 05
col 1; len 6; (6): 02 40 00 94 00 16



SQL> delete from t where object_id = 2;

已删除 1 行。

SQL> commit;

提交完成。


SQL> alter system dump datafile 9 block 573;

系统已更改。
row#0[8024] flag: ---D-, lock: 2 ---D-表示被删除
col 0; len 2; (2): c1 03
col 1; len 6; (6): 02 40 00 6d 00 1f
row#1[8012] flag: -----, lock: 0
col 0; len 2; (2): c1 04
col 1; len 6; (6): 02 40 02 2f 00 26
row#2[8000] flag: -----, lock: 0
col 0; len 2; (2): c1 05
col 1; len 6; (6): 02 40 00 94 00 16



SQL> insert into t values(1,1,1,1,1,1,sysdate,sysdate,1,1,1,1,1);

已创建 1 行。

SQL> commit;

提交完成。


SQL> alter system dump datafile 9 block 573;


kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8036
row#0[1822] flag: -----, lock: 2 -插入位置发生了变化,相当于是update提升到了pctfree保留部分
col 0; len 2; (2): c1 02
col 1; len 6; (6): 02 40 01 be 00 00
row#1[8012] flag: -----, lock: 0
col 0; len 2; (2): c1 04
col 1; len 6; (6): 02 40 02 2f 00 26
row#2[8000] flag: -----, lock: 0
col 0; len 2; (2): c1 05
col 1; len 6; (6): 02 40 00 94 00 16



SQL> delete t where object_id = 1;

已删除 1 行。

SQL> commit;

提交完成。

SQL> insert into t values(1,1,1,1,1,1,sysdate,sysdate,1,1,1,1,1);

已创建 1 行。

SQL> commit;

提交完成。

SQL>

row#0[1810] flag: -----, lock: 2 我们发现,即使删除后立即插入相同的值,也不会立即重用以前的空间1822,而是依然在新的位置1810
col 0; len 2; (2): c1 02
col 1; len 6; (6): 02 40 01 be 00 01
row#1[8012] flag: -----, lock: 0
col 0; len 2; (2): c1 04
col 1; len 6; (6): 02 40 02 2f 00 26
row#2[8000] flag: -----, lock: 0
col 0; len 2; (2): c1 05
col 1; len 6; (6): 02 40 00 94 00 16


如果继续测试下去会发生适当的时候block会重整,进一步测试后的结论

1:索引的 pctfree 是用来插入新的可容纳入该block可接受的范围的key value 的
当然pctfree也会跟 initrans ---> maxtrans 的 ITL 有关

2:删除时候的 索引上的记录被标记为 D ,该block上被查询的时候该记录存在,若该block上一旦发生下一个事务,该被标记删除记录立即被清除

 

更多内容可参考: http://www.itpub.net/showthread.php?threadid=149768

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值