关于索引重用空间的总结测试:
因为对于这方面的知识不是很了解,就做了些测试,希望大家讨论一下!
如果我的观点有误,请大家热心指正!
1。索引空间重用的一个例子
观点:一旦索引使用过存储区,就会永远在那里,并且只能被相同的值重用。(由此推测,空闲空间永远不会返回索引结构,块永远不会重用)
结论:这种观点是错误的,测试如下。
1)创建测试表:
SQL> create table t(x int,constraint t_pk primary key(x));
表已创建。
SQL> insert into t values(1);
已创建 1 行。
SQL> insert into t values(2);
已创建 1 行。
SQL> insert into t values(999999);
已创建 1 行。
SQL> set serveroutput on
SQL> exec show_space('T_PK',user,'INDEX');
Free Blocks.............................0
Total Blocks............................4
Total Bytes.............................32768
Unused Blocks...........................2
Unused Bytes............................16384
Last Used Ext FileId....................5
Last Used Ext BlockId...................634
Last Used Block.........................2
PL/SQL 过程已成功完成。
2)根据上面的观点,如果从表T中删除X=2,那个空间就永远不会重用,除非再次插入数字2。目前这个索引使用2个空间块,一个盘区地图(extent map),一个是索引数据。如果删除数据后索引条目从来不会重用,那么如果连续不断的插入和删除,并且从来不用相同的值,索引应该不断的增大。下面继续测试
SQL> begin
2 for i in 2..9999
3 loop
4 delete from t where x=i;
5 commit;
6 insert into t values(i+1);
7 commit;
8 end loop;
9 end;
10 /
PL/SQL 过程已成功完成。
SQL> exec show_space('T_PK',user,'INDEX');
Free Blocks.............................0
Total Blocks............................4
Total Bytes.............................32768
Unused Blocks...........................2
Unused Bytes............................16384
Last Used Ext FileId....................5
Last Used Ext BlockId...................634
Last Used Block.........................2
PL/SQL 过程已成功完成。
索引的空间大小没有变化,得出的结论表明索引中的空间重用了。
因为索引能够插入到适合的地方,如上面的例子,当数据2删除后,数据2的slot可以被所有位于1-9999之间的数据使用。当数据3插入后删除了,它的slot可以被所有位于1-9999之间的数据使用,这样就实现了索引的空间重用。(这一部分一开始不理解,后来看了asktom上tom的书的英文说明,才明白了,看来expert one on one翻译成了中文确实逊色很多)
2。索引空间重用的另外一个例子
索引空间从来不会返回到FREELIST上,直到块上所有的entries都被释放(通过delete,removed等),但是索引块上的空闲空间可以得到最大的使用。
1)创建测试表和测试数据
SQL> create table emp(empno int constraint emp_pk primary key,
2 ename varchar2(30));
表已创建。
SQL> insert into emp select rownum, username from
2 all_users;
已创建13行。
SQL> analyze index emp_pk validate structure;
索引已分析
SQL> select lf_rows, del_lf_rows from index_stats;
LF_ROWS DEL_LF_ROWS
---------- -----------
13 0
这里说明有13个叶子节点---13个索引行