Free Blocks.............................17
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................1
Unused Bytes............................8192
Last Used Ext FileId....................5
Last Used Ext BlockId...................546
Last Used Block.........................3
PL/SQL 过程已成功完成。
可以看到,现在大约有一半的索引在FREELIST上,这意味着块是空的(对索引FREELIST上的块必须是空的,不像堆组织表中FREELIST上的块)。
这主要证明了两点:
1)只要出现的行能重用,索引块上的空间就可以重用。
2)但一个索引块为空时,从索引结构中取走,以后可以重用。
当块上有“空闲空间”并且在索引结构的表中时,块时不可见的。在表中,可以看到空闲空间上的块,即使其中有数据。在索引中,只能看到FREELIST上完全空的块。块上只要有一个索引条目(留有空闲空间)就不能清楚的看到。
5。对于索引中“空洞”空间的重新使用
1)创建测试表和数据,然后删除偶数的数据,在索引中形成空洞。
SQL> create table t(x int);
表已创建。
SQL> begin
2 for i in 1..10000 loop
3 insert into t values(i);
4 commit;
5 end loop;
6 end;
7 /
PL/SQL 过程已成功完成。
SQL> select count(*) from t;
COUNT(*)
----------
10000
SQL> alter table t add constraint t_pk primary key(x);
表已更改。
SQL> exec show_space('T_PK',user,'INDEX');
Free Blocks.............................0
Total Blocks............................24
Total Bytes.............................196608
Unused Blocks...........................2
Unused Bytes............................16384
Last Used Ext FileId....................5
Last Used Ext BlockId...................626
Last Used Block.........................2
PL/SQL 过程已成功完成。
SQL> begin
2 for i in 1..10000 loop
3 if mod(i,2)=0 then
4 delete from t where x=i;
5 end if;
6 end loop;
7 end;
8 /
PL/SQL 过程已成功完成。
SQL> select count(*) from t;
COUNT(*)
----------
5000
SQL> commit;
提交完成。
SQL> exec show_space('T_PK',user,'INDEX');
Free Blocks.............................0
Total Blocks............................24
Total Bytes.............................196608
Unused Blocks...........................2
Unused Bytes............................16384
Last Used Ext FileId....................5
Last Used Ext BlockId...................626
Last Used Block.........................2
PL/SQL 过程已成功完成。
使用了22个block。
2)现在有5000条数据的空洞,插入范围在1-10000之外的数据5000条,理论上应该不能使用“空洞”的空间
SQL> begin
2 for i in 10001..15000 loop
3 insert into t values(i);
4 commit;
5 end loop;
6 end;
7 /
PL/SQL 过程已成功完成。
SQL> select count(*) from t;
COUNT(*)
----------
10000
SQL> commit;
提交完成。
SQL> exec show_space('T_PK',user,'INDEX');
Free Blocks.............................2
Total Blocks............................32
Total Bytes.............................262144
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................5
Last Used Ext BlockId...................46
Last Used Block.........................4
PL/SQL 过程已成功完成。
使用了30个block,可以看到这里没有使用空洞的空间。
3)插入符合“空洞”范围的数据,看看是否能利用空间。
SQL> begin
2 for i in 1..10000 loop
3 if mod(i,2)=0 then
4 insert into t values(i);
5 end if;
6 end loop;
7 end;
8 /
PL/SQL 过程已成功完成。
SQL> select count(*) from t;
COUNT(*)
----------
15000
SQL> commit;
提交完成。
SQL> exec show_space('T_PK',user,'INDEX');
Free Blocks.............................1
Total Blocks............................32
Total Bytes.............................262144
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................5
Last Used Ext BlockId...................46
Last Used Block.........................4
PL/SQL 过程已成功完成。
使用了31个block,可以看到当插入这些符合“空洞”条件的数据时,“空洞”的空间被重用了。