1. 程式人生 > >MySQL系列-B+Tree索引詳解

MySQL系列-B+Tree索引詳解

1.什麼是B+Tree?

介紹B+Tree前我們先聊一下在資料結構課程當中學習到的其他樹結構,二叉搜尋樹,平衡二叉樹搜尋樹(紅黑樹、AVL樹),不懂的同學可以先去了解一下。我們知道平衡二查搜尋樹是對二叉搜尋樹的一次改進,防止退化成線性表和樹高度過高的情況,使其搜尋單個值的複雜度為O(logN),這也就意味著在資料必須是可排序的,同時這也是Java的TreeMap(使用的是紅黑樹結構)不能存null值的原因(null無法比較)。但是為什麼又出現了B+樹呢,紅黑樹的高度雖然有一定的控制,而資料庫當中一般要把索引樹的高度控制在3-5層,這點紅黑樹顯然無法做到,B+樹是B-樹(不要讀成B減樹,而是B樹)的加強版,是一種多路平衡搜尋樹,既然它是多路平衡的,那麼就不在像紅黑樹那樣只有2個子節點了,既然有多個子節點,樹的高度就可以控制了,同時它也跟紅黑樹一樣,資料是排序的,可以快速查詢。

B+樹定義 維基百科

給大家介紹一個可以線上、視覺化的學習各種樹的網站。開啟網站

利用該網站製作的B+Tree:


可以看到,資料都在葉子節點上,並且葉子節點用指標串聯起來了,在遍歷的時候更快些。

利用該網站製作的紅黑樹:


2.為什麼用B+Tree?

那麼問題又來了,為什麼非要用這個奇怪的B+樹呢?用熟悉紅黑樹不行嗎?

因為索引是儲存在檔案中,所以讀取索引要通過磁碟io,而磁碟io相對記憶體io來說是一個相當緩慢的過程,可以理解為查詢的時候並不是把整個索引樹都載入記憶體當中(資料量一大,索引也非常龐大,甚至到幾個G),而是取樹的第一個節點,然後在進行比較之後再選擇下一個節點。這樣我們對比上面的B+樹和紅黑樹,比如查詢節點17,紅黑樹要磁碟io6次,而B+樹只要3次,也就是說磁碟io次數大致為樹的高度,這樣B+樹就脫穎而出了,成為實現索引的不二選擇。

3.MyISAM的非聚集索引

那麼在MyISAM中是如何利用B+Tree索引組織資料的呢?什麼是非聚集索引呢?

我們知道使用MyISAM引擎儲存表資料會產生三個檔案,參考我的這篇文章,.frm  .MYD .MYI

.frm 是存放表的定義資訊(MyISAM和innoDB都有這個檔案)  .MYD是存放具體的表的資料  .MYI就是存放該表的所有索引


那什麼又是非聚集索引呢?簡單來說就是索引檔案和資料檔案分開儲存,索引樹的葉子節點儲存對應資料的地址,假設table表  有主鍵id和name(name列已經建立了索引),下面畫圖說明問題:

首先準備資料


對建立name列建立索引

create index idx_name on ti(name);
show index from ti;

下面這張圖就表面了在MyISAM下索引是如何工作的


資訊量非常大,我來一一說明:這個索引樹是以建立索引的列的所有資料組織起來的,可以看出索引十分消耗儲存空間,而且葉子節點儲存的是對應的那行資料的地址,查詢的時候先通過索引樹找到對應資料的地址,再通過地址找到真正的資料。這也就是為什麼不把全部的索引一次性載入記憶體的原因, 索引太大了。

4.innoDB的聚集索引

innoDB的索引樹和MyISAM是有區別的,索引和資料放在同一個檔案裡面,主鍵索引樹的葉子節點直接儲存資料,所以叫做聚合索引。假設上面的表用的是InnoDB,建立了主鍵id索引和name這一列的索引,那麼資料又是如何組織起來的呢,下面畫圖說明:


可以看到在主鍵索引的葉子節點上直接儲存了對應的資料,資料和索引在一起,聚合索引。而且其他的索引樹的葉子節點對應的是該行資料的主鍵id,如果以name進行查詢,先在name的索引樹上找到對應的主鍵id,再通過得到的id進行查詢。這樣是為什麼innoDB查詢的時候比MyISAM慢的原因之一,innoDB必須涉及到主鍵索引,即佔用記憶體又直接多了一次主鍵索引樹的查詢。

5.為什麼推薦用自增id作為主鍵?

第一:自增的id,這個id一定是數字型別,相對於字串而言,數字的比較速度快於字串(字串需要一個字母一個字母進行  比較),在B+樹中,值的插入、查詢、 刪除都要進行比較,這樣的話用數字作為主鍵比用字串做為主鍵在比較速度上更有優勢

第二:自增的id對比亂序的UUID有什麼優勢呢,可以看到亂序的UUID在B+樹中的插入位置是非常隨機的,而自增id每次都往B+樹的最右邊進行插入,這樣B+樹的分裂操作更簡單,而且底層分配空間是分配一段連續的空間,這樣每次都像往陣列的最後插入資料,可以更合理的利用連續分配的空間,以免造成碎片過多。

第三:可以看到索引也是非常佔用磁碟空間的,對欄位小的列建索引更合理,比如對int型的列建索引就比對varchar(50)的列建索引更加節省磁碟空間。

總結:索引小,查詢快,分裂有序

參考教程: