【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程式設計師面試筆試寶典》,作者:李華榮。