B樹索引分裂


一、索引分裂

1.  什么是分裂

在開始介紹之前,我們先來搞清楚什么是索引分裂吧。“索引分裂”就是索引塊的分裂,當一次DML事務操作修改了索引塊上的數據,但是舊有的索引塊沒有足夠的空間來容納新修改的數據,那么將分裂出一個新索引塊,舊有塊的部分數據放到新開辟的索引塊上去,這個過程就稱為索引塊的分裂(INDEX BLOCK SPLIT)。

如圖1所示,當有新值插入到L4葉節點塊的時候,此時L4葉節點塊是“充滿”狀態,已經沒有足夠的空間來存儲新值了,此時會在B2分支節點下,分裂出一個新的葉節點L5來存儲新值。如果分支節點B2也是“充滿”了呢?那就要進行分支節點的分裂,即在ROOT根節點下,分裂出一個新的分支節點出來。依此類推,如果根節點也“充滿”了,則需要進行根節點的分裂。如果發生了根節點的分裂,也意味着B樹的高度(BTREE LEVEL)增加了一個層次。對真正意義上的樹來說,這種生長是好事,但對B樹索引來說,這就不是什么好事情了,B樹索引的高度需要嚴格控制的。

book_ch02_10

圖1  新值產生索引分裂

 

2.  分裂的類型

從上面的介紹來說,我們大致可以將索引分裂歸為三種類型:根節點分裂、分支節點分裂、葉節點分裂。當然,也可以說是兩種類型,因為根節點分裂實質上一種特殊的分支節點分裂。我們首要需要關注的是其中葉節點的分裂,因為它是最頻繁發生,對性能影響最直接的因素。

我們說過分裂出新節點后,會將一部分舊有的數據放到新節點上去,按照數據遷移量的比例,我們又可以將索引分裂分為兩種類型:9-1分裂和5-5分裂。如果葉節點和分支節點同時發生分裂,其分裂比例的類型是相同的,即要么都是9-1分裂,要么都是5-5分裂。

q  9-1分裂:絕大部分數據還保留在舊有節點上,僅有非常少的一部分數據遷移到新節點上。

q  5-5分裂:舊節點和新節點上的數據比例幾乎是持平的。

我們通常所說的索引分裂,大部分情況都指的是9-1的分裂。當事務向索引的最右側的葉節點上插入一條大於或等於現有索引塊上最大值的數據,且該索引塊上不存在其他未提交的事務,如果沒有足夠的空間,就會發生9-1分裂。

很遺憾的是,當發生左側節點上插入數據的時候,發生9-1分裂就會出現一些問題。如圖2所示,當向左側分支節點插入新值,即使其兄弟右側分支節點數據區中沒有數據(或者說沒有右節點),它們的父節點都會發生分裂,極端情況下甚至會促使B樹的高度增長,這對索引性能來說是很悲劇的,這一缺陷在10g以前的版本中都是存在的。

book_ch02_11

圖2  左節點9-1分裂

 

從Oracle 10g開始,對於左側節點的數據插入行為,引進了5-5分裂的方式,修正了9-1分裂造成的缺陷。如圖3所示,當左側分支節點B1已經“充滿”狀態,會去判斷其兄弟右側分支節點B2是否有空間,如果有,則將部分數據(5:5的比例)遷移到右側分支節點上,這樣就避免了分支節點甚至根節點的分裂。

book_ch02_12

圖3  左節點5-5分裂

5-5分裂的方式也不是萬能的,如果過於頻繁的5-5分裂也會造成索引空間使用率不高,使得索引結構看上去像一個“虛胖子”,不夠“結實’,同樣會造成性能問題。

那什么時候會發生5-5分裂呢?簡單地來說就是在索引需要分裂,但不能進行9-1分裂的時候就會觸發5-5分裂。這聽起來像一句廢話,可將9-1分裂的條件反過來看,也正是5-5分裂發生的條件:

q  左側節點發生新值插入時(新值小於索引中的最大值);

q  發生DML操作,索引塊上沒有足夠空間分配新的ITL槽;

q  新值待插入的索引塊上存在其他未提交的事務。

對比一下9-1分裂和5-5分裂的發生場景。9-1分裂通常是索引的鍵值是遞增的,表上的事務並發量比較低,可保證新的數據塊上有較大的空閑空間插入新值。5-5分裂通常是表上的事務並發度較高,操作的數據是無序的,需保證分裂的新舊數據塊上有相對較大的空閑空間以容納新事務的操作。

總體來看,不論是9-1分裂還是5-5分裂,對於性能來說,都不是什么好事。索引塊的分裂意味着索引數據一定范圍上的重組,其維護代價都是非常高昂的,應該盡可能地避免不必要的分裂發生。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM