【DB笔试面试566】在Oracle中,什么是索引分裂?

  • 2019 年 10 月 10 日
  • 筆記

题目部分

在Oracle中,什么是索引分裂?

答案部分

索引分裂(Index Block Split),就是索引块的分裂。当一次DML操作修改了索引块上的数据,但是旧有的索引块没有足够的空间去容纳新修改的数据时,将分裂出一个新的索引块,旧有块的部分数据放到新开辟的索引块上去,这个过程就称为索引块的分裂,简称索引分裂。

在分裂的过程中前台进程需要等待分裂完成之后才能继续操作。如果此时其它会话也要修改这个索引块的数据,那么将会出现索引块的竞争,等待以“enq: TX – index contention”的形式体现,该事件是一个与索引分裂直接相关的等待事件。一般索引块的分裂持有资源和释放非常迅速,并不会对数据库造成严重的性能影响,但是对表操作并发量很大的情况下可能导致严重的竞争。当索引分裂发生时,负责实施分裂的进程会持有相关的队列锁,直到该进程完成分裂操作才会释放该队列锁。在这个过程中负责分裂的进程需要找到合适的新块并将对应的数据移动到该新块中。若在此分裂的过程中,有其它进程INSERT数据到该索引块中,则将进入enq: TX – index contention等待,直到分裂结束锁被释放。

索引分裂有如下几种情况:

(1)按照分裂对象分:

l 叶子节点分裂:叶子节点上没有足够的空间容纳新插入的数据。叶子节点分裂的情况最频繁发生,对性能影响最直接。

l 枝节点分裂:其下层的节点分裂,会导致在该节点上增加一条记录指向新加的节点,当该节点空间不足时,会发生分裂。

l 根节点分裂:特殊的枝节点分裂,分裂需要两个新的数据块,将原有数据转移至两个新节点,原有节点上生成两条记录分别指向新增的数据块。

(2)按照分裂数据块比例分:

l 9-1分裂:当事务向索引的最右侧的叶节点上插入一条大于或等于现有索引块上最大值的数据,且该索引块上不存在其它未提交的事务,如果没有足够的空间,那么就会发生9-1分裂。绝大部分数据还保留在旧有节点上,仅有非常少的一部分数据迁移到新节点上。

l 5-5分裂:当发生5-5分裂时,有一半索引记录仍存在当前块,而另一半数据移动到新的节点中,旧节点和新节点上的数据比例几乎是持平的。5-5分裂发生的条件:

1、当左侧节点发生新值插入时(插入到叶子节点中的索引键值小于该块中的最大值)。

2、当发生DML操作时,索引块上没有足够空间分配新的ITL槽。

3、当新插入数据大于或等于索引中最大值时,但是数据块上还存在其它未提交的事务。

对性能来说,无论是9-1分裂,还是5-5分裂,都会影响系统的性能。通过10224事件可以生成索引块分裂及删除的trace:

SYS@lhrdb> ! oerr ora 10224  10224, 00000, "index block split/delete trace"  // *Cause:  // *Action:  SYS@lhrdb> ALTER SESSION SET EVENTS '10224 TRACE NAME CONTEXT FOREVER,LEVEL 10';  Session altered  SYS@lhrdb> INSERT INTO T_IBS_LHR SELECT LEVEL FROM DUAL CONNECT BY LEVEL<50000;  49999 rows inserted  SYS@lhrdb> COMMIT;  Commit complete  SYS@lhrdb> ALTER SESSION SET EVENTS '10224 TRACE NAME CONTEXT OFF';  Session altered    

索引分裂常常发生在主键列上,在这种情况下,可以考虑将该主键修改为反转(REVERSE)类型的主键。若主键是通过序列、时间戳或按某种规则单调生成的主键,则可以使用反转索引来有效地降低索引“单向右增长”(Right-Growing Index)的可能性。语句如下所示:

CREATE  INDEX  ...   REVERSE;    ALTER  INDEX  ...  REBUILD  ONLINE  REVERSE;  

在发生索引分裂等待的时候,也可以根据需要将索引改造为分区索引。通过HASH将索引分成一个一个小块,这样竞争就不会聚集在最右边的节点上。通过HASH分区索引在一定程度上就可以缓解插入数据的竞争问题。

& 说明:

有关索引分裂的内容可以参考我的BLOG:http://blog.itpub.net/26736162/viewspace-2139232/

本文选自《Oracle程序员面试笔试宝典》,作者:李华荣。