1. 程式人生 > 資料庫 >MySQL B+Tree索引概念

MySQL B+Tree索引概念

索引作用是為了提高資料檢索效率,通過二分查詢法快速定位資料範圍.
下圖是B樹索引與B+Tree索引儲存原理圖(本人畫太慢了,扣的網圖):
B-Tree索引:
在這裡插入圖片描述
B+Tree索引:(網上原圖不是太準確,所以我調整了一下)

在這裡插入圖片描述

對上圖的概念解釋:

樹節點的概念:

根節點:最頂層的節點,有且只有一個節點 (對應圖中磁碟塊1)
葉子節點:最底層的節點 (對應圖中磁碟塊4~9)
內節點:除根節點與葉子節點的節點都是內節點 (對應圖中磁碟塊2和3)

頁:
頁是mysql與磁碟互動的基本單位,預設大小16K,使用者資料與索引資料是存放到頁中的(這個說法對MyISAM不準確,後面會說),圖中標記的磁碟塊就是頁,也就是有9個頁,頁4(磁碟塊4)中儲存了4條使用者資料行,頁6(磁碟塊6)儲存了2條使用者資料行.每一層的頁與頁之間是雙向的,注意是每一層的頁(節點).葉子節點中的資料行並不一定按照圖中的順序儲存的,比如磁碟塊4中的儲存的順序可能是5 10 9 3只是內部通過一些屬性形成連結串列,這樣連結串列的順序就是圖中3->5->9->10的順序.

B-Tree與B+Tree區別:
上面兩張圖中可以看出,B-Tree索引所有的節點中都存放了data,也就是我們插入表中的資料行,而B+Tree索引只有葉子節點才存放真實資料,非葉子節點存放的是索引資料(頁指標與主鍵值).關於B-Tree其他的不說了,重點在於Mysql中使用的B+Tree.

圖中樹只有三層,實際有幾層?
這個不一定,跟每行資料的大小以及總的資料量條目數有關係,通常情況下就是3層,但是資料量很小的時候有兩層(沒有內節點),資料量很大的時候會有超過3層(但是一般不會出現,有那麼大資料量就會用大資料nosql資料庫儲存了),所有我們一般把B+Tree當成3層就可以了.

聚簇索引
上圖中的B-Tree與B+Tree圖是聚簇索引,聚簇索引與二級索引的區別在於聚簇索引的葉子節點儲存的是真實資料,二級索引的葉子節點儲存的是指向真實資料的指標.

B+Tree索引

因為要完全準確的描述索引需要大量篇幅講底層從行到頁的儲存,而那一部分內容不影響我們理解mysql中的索引,所以感興趣的話可以看我的另外兩篇博文:


以下篇幅不特別指出的話,就是以主鍵的聚簇索引展開說明的,二級索引會有特殊說明.

檢索資料
比如我們要根據圖中主鍵檢索15的資料,首先定位到根節點(這個跟節點地址是不會變動的,後面說),然後1<15<28,因為1跟28儲存的分別是頁2頁3中的最小值,所以我們可以定位到15的資料在頁2中,在頁2中定位15在頁5中,到頁中查詢到15的data.
上面的過程是我們可以理解成的過程,實際過程瞭解一下即可:首先頁中(無論是什麼節點)資料是分組的,每個組對應一個slot,slot裡面儲存的是編號與組內最大的主鍵值.下面畫的是葉子節點,這個頁中有1~20 二十條資料(頁大小16k所以根據每一資料行的大小可以儲存2到多條資料,最少儲存2條是硬性規定),我們把1到20條資料分成五組(實際分組規則三言兩語說不清楚,大部分組內是4-8條資料)

在這裡插入圖片描述
檢索資料是通過slot進行二分查詢法,圖中五個slot,如果要檢索主鍵15的資料,先通過二分查詢法(二分查詢法不知道的話就百度吧)5個slot先校驗slot2中的主鍵,是12,比15小找右邊,再根據二分查詢法校驗slot3中的主鍵值,為16比15大,slot中儲存的最大的主鍵值,所以定位15在slot3中,然後遍歷slot3中的資料獲取到主鍵為15的資料即可.每個葉子節點中取最小的主鍵值,加上這個頁的指標,就組成了內節點的一條資料,如果有20個葉子節點頁,那麼內節點頁中就有20條資料,依次對根節點->內節點->葉子節點中的slot通過二分查詢法,最終定位到葉子節點的真實資料.

生成B+Tree索引
剛開始表中沒有資料,就會建立聚簇索引根節點,根節點中也沒有資料,隨著資料的插入,根節點慢慢就會填充資料(主鍵值與頁指標),隨著資料量越來越大,這時根節點存放不下就需要頁分裂,由一個頁變成兩個頁,但是根節點地址是不變的,並且根節點只能有一個,所以首先根節點(頁1)中的資料複製到新的頁(頁2)中,新的頁再分裂出一個頁(頁3),這兩個頁就變成了內節點,原來的根節點就會刪除原有的資料,分別儲存頁2與頁3的的最小主鍵值與頁2與頁3的指標.如下圖所示
在這裡插入圖片描述
聚簇索引與二級索引
對於InnoDB而言,表無論是否手動指定主鍵,都會維護一個主鍵,如果沒有指定主鍵,那麼會找唯一非null索引作為主鍵,如果連唯一非null索引都沒有,那麼InnoDB會自己維護一個主鍵row_id.主鍵是唯一非null的,所以可以進行完全排序.根據主鍵生成的索引是聚簇索引,其他索引都是二級索引(唯一索引,普通索引,複合索引),也叫輔助索引.
聚簇索引的葉子節點儲存的是真實資料,二級索引葉子節點儲存的是二級索引列值+主鍵值,聚簇索引非葉子節點儲存的是主鍵值與頁的指標,而二級索引非葉子節點儲存的是二級索引列的值和頁的指標以及主鍵值,因為二級索引可能會重複,索引重複時可以根據主鍵值進行排序,可能會有疑問,為什麼二級索引的葉子節點不儲存真實資料或者儲存真實資料所在的頁號呢,不儲存真實資料是空間考慮,有多少個索引就要維護多少份真實資料,顯然空間浪費嚴重;不儲存真實資料頁號是因為資料的頁號可能會變(頁分裂或者頁合併),變了就要額外地去維護二級索引.
MyISAM無論是主鍵還是二級索引都是二級索引,他們的葉子節點儲存的都是指向資料的行號,因為MyISAM的真實資料是按照插入順序寫入到一個檔案中的,葉子節點儲存的行號就是指向真實資料所在行的指標,所以MyISAM的使用二級索引檢索時速度要比InnoDB快(InnoDB的二級索引查詢的是主鍵值,還要回表到主鍵索引中查詢真實資料)