mysql數據庫爲什麼使用B+樹

 

首先要了解mysql的io過程

前面提到了訪問磁盤,那麼這裏先簡單介紹一下磁盤IO和預讀,磁盤讀取數據靠的是機械運動,每次讀取數據花費的時間可以分爲尋道時間、旋轉延遲、傳輸時間三個部分,尋道時間指的是磁臂移動到指定磁道所需要的時間,主流磁盤一般在5ms以下;旋轉延遲就是我們經常聽說的磁盤轉速,比如一個磁盤7200轉,表示每分鐘能轉7200次,也就是說1秒鐘能轉120次,旋轉延遲就是1/120/2 = 4.17ms;傳輸時間指的是從磁盤讀出或將數據寫入磁盤的時間,一般在零點幾毫秒,相對於前兩個時間可以忽略不計。那麼訪問一次磁盤的時間,即一次磁盤IO的時間約等於5+4.17 = 9ms左右,聽起來還挺不錯的,但要知道一臺500 -MIPS(Million Instructions Per Second)的機器每秒可以執行5億條指令,因爲指令依靠的是電的性質,換句話說執行一次IO的時間可以執行約450萬條指令,數據庫動輒十萬百萬乃至千萬級數據,每次9毫秒的時間,顯然是個災難。下圖是計算機硬件延遲的對比圖,供大家參考:

204-MySQL索引原理-01.png?x-oss-process=style/watermark

考慮到磁盤IO是非常高昂的操作,計算機操作系統做了一些優化,當一次IO時,不光把當前磁盤地址的數據,而是把相鄰的數據也都讀取到內存緩衝區內,因爲局部預讀性原理告訴我們,當計算機訪問一個地址的數據的時候,與其相鄰的數據也會很快被訪問到。每一次IO讀取的數據我們稱之爲一頁(page)。具體一頁有多大數據跟操作系統有關,一般爲4k或8k,也就是我們讀取一頁內的數據時候,實際上才發生了一次IO,這個理論對於索引的數據結構設計非常有幫助。

結論:每個節點的索引key值越多,對於一次IO拿到的有效數據越多。


1. 與二叉樹相比 


二叉樹相比於順序查找的確減少了查找次數,但是在最壞情況下,二叉樹有可能退化爲順序查找。而且就二叉樹本身來說,當數據庫的數據量特別大時,其層數也將特別大。二叉樹的高度一般是log_2^n,B樹的高度是log_t^((n+1)/2) + 1,其高度約比B樹大lgt倍。n是節點總數,t是樹的最小度數。 
 è¿éåå¾çæè¿°
假如每個盤塊可以正好存放一個B樹的結點(正好存放2個文件名)。那麼一個BTNODE結點就代表一個盤塊,而子樹指針就是存放另外一個盤塊的地址。

下面,咱們來模擬下B樹索引查找文件29的過程:

根據根結點指針找到文件目錄的根磁盤塊1,將其中的信息導入內存。【磁盤IO操作 1次】
此時內存中有兩個文件名17、35和三個存儲其他磁盤頁面地址的數據。根據算法我們發現:17<29<35,因此我們找到指針p2。
根據p2指針,我們定位到磁盤塊3,並將其中的信息導入內存。【磁盤IO操作 2次】
此時內存中有兩個文件名26,30和三個存儲其他磁盤頁面地址的數據。根據算法我們發現:26<29<30,因此我們找到指針p2。
根據p2指針,我們定位到磁盤塊8,並將其中的信息導入內存。【磁盤IO操作 3次】
此時內存中有兩個文件名28,29。根據算法我們查找到文件名29,並定位了該文件內存的磁盤地址。

2. 與B樹相比 


B樹在提高IO性能的同時,並沒與解決元素遍歷時效率低下的問題,正是爲了解決這個問題,B+數應運而生。B+數只需遍歷葉子節點即可實現整棵樹的遍歷,而B樹必須使用中序遍歷按序掃庫,B+樹支持範圍查詢非常方便。這纔是數據庫選用B+樹的主要原因。

另外,最後說一下,並不是說B+樹就比B樹好,有很多基於頻率的搜索是選用B樹,越頻繁query的結點越往根上走,前提是需要對query做統計,而且要對key做一些變化。 
無論是B樹還是B+樹由於前邊幾層反覆query,因此早已被加載入內存,不會出現讀磁盤IO。一般啓動的時候,就會主動換入內存。在內存中B+樹並沒有優勢,只有在磁盤中B+樹的威力才能顯現。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章