首页 » ORACLE » index block splits

index block splits

index是一个逻辑有顺序的结构并非物理存储block上排序,它总是可以把每个键值有顺序的逻辑排放,索引的高度总是平衡的,并且index leaf block就像一个双向链表,在index leaf block上会记录前一块的地址和后一块的地址,这样在index range scan 是就可以很方便的横向扫描,并且对于索引列的update 操作,其实是对Key values的deleting old value and insering the new values。

<pre>
下面我举个例子来说明b-tree index 的分裂情况

比如下面这个结构
—– begin tree dump
branch: 0x1000213 16777747 (0: nrow: 2, level: 1)
leaf: 0x1000214 16777748 (-1: nrow: 540 rrow: 540)
leaf: 0x1000215 16777749 (0: nrow: 460 rrow: 460)
—– end tree dump

一个分支下有两个叶子块,总共是1000个值,因为insert的是1到1000,所以第一块上的值就是1到540,这个可以dump block转储出来确认

那如果这时再insert值为 500 到520的值进去,又回如何呢?

这样就会产生一种index block split 50-50,这也是默认的分裂方式,分裂后的节点分布如下
—– begin tree dump

*** 2012-05-01 05:32:40.346
branch: 0x1000213 16777747 (0: nrow: 3, level: 1)
leaf: 0x1000214 16777748 (-1: nrow: 279 rrow: 279)
leaf: 0x1000217 16777751 (0: nrow: 282 rrow: 282)
leaf: 0x1000215 16777749 (1: nrow: 460 rrow: 460)
—– end tree dump

如果原来块上没有可用空间,就会从原来的块中拿出50% 的key value,和新加入值组成新的块,同时还会更新第三个块的指针,因为此块还是按key的顺序出现了插队现象(加塞儿)

同时如果观查统计信息会发现产生了leaf node splits

anbob@sql>select b.name,a.value from v$sesstat a,v$statname b where a.statistic#=b.statistic# and b.name like ‘%split%’ and sid in(select sid from v$mystat where rownum=1);
NAME                                                                  VALUE
—————————————————————- ———-
leaf node splits                                                          1
leaf node 90-10 splits                                                    0
branch node splits                                                        0
root node splits                                                          0
queue splits                                                              0

再看另外一种情况,如果insert 大于当前的最大值呢?比如1500-1720,也就是向右侧插入新数据,如果第三个index leaf block放不下呢?
这样就会产生另一种leaf node 90-10 splits,这是在10g中才起作用的

NAME                                                                  VALUE
—————————————————————- ———-
leaf node splits                                                          1
leaf node 90-10 splits                                                    1
branch node splits                                                        0
root node splits                                                          0
queue splits                                                              0

结构变成了下面的情况
—– begin tree dump
branch: 0x1000213 16777747 (0: nrow: 4, level: 1)
leaf: 0x1000214 16777748 (-1: nrow: 279 rrow: 279)
leaf: 0x1000217 16777751 (0: nrow: 282 rrow: 282)
leaf: 0x1000215 16777749 (1: nrow: 533 rrow: 533)
leaf: 0x1000216 16777750 (2: nrow: 148 rrow: 148)
—– end tree dump

不过注意leaf node splits 包含leaf node 90-10 splits,leaf node splits是50-50和90-10的总和。

如果在索引列发生了delete会怎样呢?
oracle从来不会把新插入的值放到以前分配好的块上,即使那个块上有90%的可用空间,新增加的值总是去b-tree结构的尾部分配新块,如果以前leaf block上的所有Key都标志为deleted,那么这个块就可以再次重复利用,分配给下一个leaf block,所以b-tree 物理块并不是有序的。

</pre>

打赏

对不起,这篇文章暂时关闭评论。