MySQL的InnoDB索引結構採用B+樹,B+樹什麼概念呢,二叉樹大家都知道,我們都清楚隨着葉子結點的不斷增加,二叉樹的高度不斷增加,查找某一個節點耗時就會增加,性能就會不斷降低,B+樹就是解決這個問題的。
B樹和B+樹
在一棵M階B樹中,每個節點最多有 M-1 個關鍵字,根節點最少可以只有一個關鍵字,非根節點最少有 Math.ceil(m/2)-1個關鍵字,下圖是一棵階數爲3的樹
看下圖我們說說B樹的特點,很明顯一個節點存儲的數據更多了,不需要很高的高度就可以存儲更多的數據,把一個節點看作一個磁盤,我們發現查找一個數據時可以減少磁盤IO次數,B樹的每個節點都有data域,
看下圖我們說說B+樹的特點,首先明確一點,B+樹是在B樹的基礎上演化而來的,我們就說不同點,只有葉子節點纔有data域,葉子節點包含所有的數據,葉子節點通過指針鏈接形成雙向鏈表。
B/B+樹是爲了磁盤或其它存儲設備而設計的一種平衡多路查找樹(相對於二叉,B樹每個內節點有多個分支),與紅黑樹相比,在相同的的節點的情況下,一顆B/B+樹的高度遠遠小於紅黑樹的高度(在下面B/B+樹的性能分析中會提到)。B/B+樹上操作的時間通常由存取磁盤的時間和CPU計算時間這兩部分構成,而CPU的速度非常快,所以B樹的操作效率取決於訪問磁盤的次數,關鍵字總數相同的情況下B樹的高度越小,磁盤I/O所花的時間越少
爲什麼InnoDB選擇B+樹而不是B樹呢
還是上面兩張圖,對照着看,我們能夠得出一下結論
B+樹的磁盤讀取代價低, 樹每個節點都有data域,B+樹只有葉子節纔有,假設每個節點大小16KB,那麼B+樹比B樹能存儲更多的關鍵字,一次性讀入內存的關鍵字的內存也會更多,B+樹的高度也會比B樹低,磁盤IO次數會更少。
B+樹對範圍查詢更友好,方便遍歷,B樹葉子節點沒有鏈接,而B+樹葉子節點通過雙向指針鏈接,可以很方便的進行範圍查詢,比如where條件中 age >=3 and age <20,,那麼當找到3時就可以順着指針找到20,而B樹是不可以的。
B+樹查詢效率穩定性更好, 在B+樹中,由於分支節點並不是最終指向文件內容的節點,分支節點只是葉子節點的索引,所以對於任意關鍵字的查找都必須從根節點走到分支節點,所有關鍵字查詢路徑長度相同,每個數據查詢效率相當。而對於B樹而言,其分支節點上也保存有數據,對於每一個數據的查詢所走的路徑長度是不一樣的,效率也不一樣,B樹穩定性不如B+樹好
我們仔細想想我們SQL常見的查詢中,總結起來是不是也就是等於查詢, 範圍查詢
InnoDB非主鍵索引怎麼存儲呢?
我們上面介紹的只是主鍵索引是這樣存儲的,那麼非主鍵索引呢,其實非主鍵索引也B+樹的,只有非主鍵索引的葉子節點存儲的不是行記錄數據,而是主鍵值,通過主鍵值再次索引獲取所需要的數據。我畫一個粗略的見圖來表示
總結一下B+樹索引
採用了多叉樹的結構,降低了樹的高度,減少了磁盤IO次數,通過對所有葉子節點通過指針雙向鏈接,方便的提供了遍歷所有數據的特性,同時數據也是嚴格有序的,方便範圍查詢,查詢效率的穩定性也非常好。