mysql索引原理------爲什麼mysql索引要選擇B+樹這種數據結構,而不是二叉樹,紅黑樹,B樹?

二叉樹

什麼是二叉樹

在計算機科學中,二叉樹是每個結點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)。二叉樹常被用於實現二叉查找樹和二叉堆。
一棵深度爲k,且有2^k-1個結點的二叉樹,稱爲滿二叉樹。這種樹的特點是每一層上的結點數都是最大結點數。而在一棵二叉樹中,除最後一層外,若其餘層都是滿的,並且或者最後一層是滿的,或者是在右邊缺少連續若干結點,則此二叉樹爲完全二叉樹。具有n個結點的完全二叉樹的深度爲floor(log2n)+1。深度爲k的完全二叉樹,至少有2k-1個葉子結點,至多有2k-1個結點。

二叉樹的結構

在這裏插入圖片描述
圖片上可以明顯看到樹的高度是6,如果我們要查詢6這個元素的話我們要進行6次查詢,這顯然不滿足實際開發得需求。
然後是

紅黑樹

什麼是紅黑樹

紅黑樹也是二叉查找樹,我們知道,二叉查找樹這一數據結構並不難,而紅黑樹之所以難是難在它是自平衡的二叉查找樹,在進行插入和刪除等可能會破壞樹的平衡的操作時,需要重新自處理達到平衡狀態。

紅黑樹的特性

性質1:每個節點要麼是黑色,要麼是紅色。
性質2:根節點是黑色。
性質3:每個葉子節點(NIL)是黑色。
性質4:每個紅色結點的兩個子結點一定都是黑色。
性質5:任意一結點到每個葉子結點的路徑都包含數量相同的黑結點。
從性質5又可以推出:

性質5.1:如果一個結點存在黑子結點,那麼該結點肯定有兩個子結點

紅黑樹的平衡

前面講到紅黑樹能自平衡,它靠的是什麼?三種操作:左旋、右旋和變色。

左旋:以某個結點作爲支點(旋轉結點),其右子結點變爲旋轉結點的父結點,右子結點的左子結點變爲旋轉結點的右子結點,左子結點保持不變。
右旋:以某個結點作爲支點(旋轉結點),其左子結點變爲旋轉結點的父結點,左子結點的右子結點變爲旋轉結點的左子結點,右子結點保持不變。
變色:結點的顏色由紅變黑或由黑變紅。

紅黑樹的結構

在這裏插入圖片描述
可以明顯的看到同樣的元素,在紅黑樹的存儲的高度比二叉樹要低,紅黑樹會同股喲左旋右旋的操作來減少樹的高度,從而到達減少我們查詢樹種元素的次數來提高查詢效率,當然這個就滿足我們對數據庫查詢的要求了嗎?
下面我們來看看B樹

B樹

什麼是B樹

B樹和平衡二叉樹稍有不同的是B樹屬於多叉樹又名平衡多路查找樹

B樹的結構

在這裏插入圖片描述
圖片上可以明顯看到,B樹和紅黑樹相比,B樹變胖了,一個node上可以存儲多分數據,而且B樹是多叉樹,就是說一個B樹的node可以有多個子節點,這相比紅黑樹又進一步減少了樹的高度,當然這還是不滿足索引的需要。我們再看看B+樹:

B+樹

什麼是B+樹?

B+樹是B樹的一個升級版,相對於B樹來說B+樹更充分的利用了節點的空間,讓查詢速度更加穩定,其速度完全接近於二分法查找。

B+樹的特點

特點

1、B+樹的層級更少:相較於B樹B+每個非葉子節點存儲的關鍵字數更多,樹的層級更少所以查詢數據更快;

2、B+樹查詢速度更穩定:B+所有關鍵字數據地址都存在葉子節點上,所以每次查找的次數都相同所以查詢速度要比B樹更穩定;

3、B+樹天然具備排序功能:B+樹所有的葉子節點數據構成了一個有序鏈表,在查詢大小區間的數據時候更方便,數據緊密性很高,緩存的命中率也會比B樹高。

4、B+樹全節點遍歷更快:B+樹遍歷整棵樹只需要遍歷所有的葉子節點即可,,而不需要像B樹一樣需要對每一層進行遍歷,這有利於數據庫做全表掃描。

B樹相對於B+樹的優點是,如果經常訪問的數據離根節點很近,而B樹的非葉子節點本身存有關鍵字其數據的地址,所以這種數據檢索的時候會要比B+樹快。
爲什麼說B+樹查找的效率要比B樹更高、更穩定;我們先看看兩者的區別
在這裏插入圖片描述
圖片上我們可以看到,B+樹的數據都會濃郁()存儲在葉子結點,而且葉子結點之間都又指針指向,這會提高查詢範圍的效率。

所以B+樹纔是最適合做查詢索引的樹結構。

什麼是mysql中的頁

我們都知道mysql中的數據只存放在磁盤上的,那麼我們查詢數據的時候會從磁盤上去讀取數據,這樣讀取一次就是一次磁盤IO,一次磁盤IO最多可以讀取16K,這就是mysql中的一頁。

計算高度爲3的B+樹能存放多少記錄

上面說到mysq的中默認一頁是16K,我們可以用
SHOW VARIABLES LIKE ‘innodb_page_size’;查到
在這裏插入圖片描述
所以我們B+樹的葉子結點也要存儲16K的數據,這是爲什麼呢?因爲如果葉子結點數據小於16k,那麼我們還是要做一次磁盤IO去讀取到內存,這樣會造成IO的浪費,如果大於16K我們就需要兩次磁盤IO。所以16K最爲合適。

在B+樹中的非葉子結點最會存儲指針和主健,這裏我假設在msyql innodb引擎中主健是bigint類型 爲8字節,指針爲6字節,那麼在一棵高度爲2的B+樹中,非葉子結點能存放的指針數就是16384(16K)/(8+6)=1170
如果高度爲3的話 就是1170^3-1=1170X1170
(這裏可能有些同學有點疑惑爲啥是1170X1170,這裏很好理解,在根節點能存1170個指針那個每一個指針能指向一個非葉子結點,一個非葉子結點又能存1170個指針,所以是這顆高度爲3的B+樹總共有1170X1170個指針)
,這裏假設每行記錄的大小是1K,一個葉子結點就能存儲16行
所以高度爲3的B+樹能存儲1170X1170X16=21902400行。約等於2.19千萬行數據。本文大多手動碼字,有描述錯誤或者不清的地方,請指正。謝謝

本文參考:
https://zhuanlan.zhihu.com/p/27700617
https://www.jianshu.com/p/e136ec79235c
https://www.cnblogs.com/fanBlog/p/11394035.html

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