徹底搞懂這些:二叉樹今野、平衡二叉樹、B-Tree罐农、B+Tree

<article class="syl-article-base tt-article-content syl-page-article syl-device-pc" style="box-sizing: border-box; display: block; padding: 0px; text-align: justify; word-wrap: break-word; word-break: break-word; overflow: hidden; color: rgb(34, 34, 34); font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif; line-height: 1.667; font-size: 18px; margin-bottom: 20px;">

背景

一般說MySQL的索引条霜,都清楚其索引主要以B+樹為主,此外還有Hash啃匿、RTree蛔外、FullText蛆楞。本文簡要說明一下MySQL的B+Tree索引,以及和其相關的二叉樹夹厌、平衡二叉樹豹爹、B-Tree,相關的知識網上很多矛纹,為了方便自己更快臂聋、清楚的了解,文本聚合一些內容以及個人的一些理解或南。

說明

二叉查找樹(BST)

概念

二叉查找樹是基于二分查找法來提高數(shù)據(jù)查找速度的二叉樹的數(shù)據(jù)結構孩等;

特點

二叉查找樹是采用二分查找法把數(shù)據(jù)按規(guī)則組裝成一個樹形結構的數(shù)據(jù),減少無關數(shù)據(jù)的檢索采够,提升了數(shù)據(jù)檢索的速度肄方;二叉樹的數(shù)據(jù)結構有以下規(guī)則:

(1)非葉子節(jié)點只能允許最多兩個子節(jié)點存在。

(2)每一個非葉子節(jié)點數(shù)據(jù)分布規(guī)則為左邊的子節(jié)點小當前節(jié)點的值蹬癌,右邊的子節(jié)點大于當前節(jié)點的值权她;

即二叉查找樹的特點就是任何節(jié)點的左子節(jié)點的鍵值都小于當前節(jié)點的鍵值,右子節(jié)點的鍵值都大于當前節(jié)點的鍵值逝薪。頂端的節(jié)點稱為根節(jié)點隅要,沒有子節(jié)點的節(jié)點我們稱之為葉節(jié)點。以下圖中的圓為二叉查找樹的節(jié)點董济,節(jié)點中存儲了鍵(key)和數(shù)據(jù)(data)

image.png

查找結點值的方法就是二分查找法:查找次數(shù)就是樹的高度步清。二叉查找樹可以任意地構造 如果向一方傾斜的二叉樹是不平衡的,查詢效率就低了虏肾,二叉查找樹變成了一個鏈表廓啊。如下圖:


image.png

在上面的2張圖中,查找鍵值為17的數(shù)據(jù)询微,第一張圖里需要3次IO崖瞭,第2張圖里需要7次IO狂巢。原因是二叉查找樹變得不平衡了撑毛,也就是高度太高了,從而導致查找效率的不穩(wěn)定唧领。為了解決這個問題藻雌,需要保證二叉查找樹一直保持平衡,就需要用到平衡二叉樹了斩个。

平衡二叉樹(AVL)

在滿足二叉查找樹特性的基礎上胯杭,如不是空樹,任何一個結點的左子樹與右子樹都是平衡二叉樹受啥,并且高度之差的絕對值不超過 1做个。類似于:

image.png

關于平衡二叉樹的可以看 什么是平衡二叉樹(AVL)該文章說明鸽心,平衡二叉樹相比于二叉查找樹來說,查找效率更穩(wěn)定居暖,總體的查找速度也更快顽频。需要注意的是平衡二叉樹是每個節(jié)點只存儲一個鍵值和數(shù)據(jù)的。

B樹(B-Tree)

概念:

B樹和平衡二叉樹不同太闺,B樹屬于多叉樹又名平衡多路查找樹(查找路徑不只兩個)糯景,數(shù)據(jù)庫索引里大量使用者B-Tree和B+Tree的數(shù)據(jù)結構。

特點:

  1. 排序方式:所有節(jié)點關鍵字是按遞增次序排列省骂,并遵循左小右大原則蟀淮;
  2. 子節(jié)點數(shù):非葉節(jié)點的子節(jié)點數(shù)>1,且<=M 钞澳,且M>=2怠惶,空樹除外(注:M階代表一個樹節(jié)點最多有多少個查找路徑,M=M路轧粟,當M=2則是2叉樹,M=3則是3叉)甚疟;
  3. 關鍵字數(shù):枝節(jié)點的關鍵字數(shù)量大于等于ceil(M/2)-1個且小于等于M-1個(注:ceil()是個朝正無窮方向取整的函數(shù) 如ceil(1.1)結果為2);
  4. 所有葉子節(jié)點均在同一層、葉子節(jié)點除了包含了關鍵字還包含了數(shù)據(jù);

最后我們用一個圖和一個實際的例子來理解B樹(這里為了理解方便我就直接用實際字母的大小來排列C>B>A)

image.png

圖中可以看到BTree的單個節(jié)點可以存儲多個鍵值和數(shù)據(jù)的平衡樹逃延。和平衡二叉樹相比:比如要存儲海量的數(shù)據(jù)览妖,因為(平衡)二叉樹的每個節(jié)點只存儲一個鍵值和數(shù)據(jù)的,二叉樹的節(jié)點將會非常多揽祥,高度也會及其高讽膏,當查找數(shù)據(jù)時也會進行很多次磁盤IO,查找的效率將會極低拄丰,大致的二叉樹結構如下:

image.png

為了解決平衡二叉樹的這個弊端府树,需要一種單個節(jié)點可以存儲多個鍵值和數(shù)據(jù)的平衡樹(BTree):

image.png

從上圖可以看出,B樹相對于平衡二叉樹料按,每個節(jié)點存儲了更多的鍵值(key)和數(shù)據(jù)(data)奄侠,并且每個節(jié)點擁有更多的子節(jié)點,子節(jié)點的個數(shù)一般稱為階载矿,上述圖中的B樹為3階B樹垄潮,高度也會很低∶瓶基于這個特性弯洗,B樹查找數(shù)據(jù)讀取磁盤的次數(shù)將會很少,數(shù)據(jù)的查找效率也會比平衡二叉樹高很多逢勾。

假如我們要查找id=28的用戶信息牡整,那么我們在上圖B樹中查找的流程如下:

  1. 先找到根節(jié)點也就是頁1,判斷28在鍵值17和35之間溺拱,我們那么我們根據(jù)頁1中的指針p2找到頁3逃贝。
  2. 將28和頁3中的鍵值相比較谣辞,28在26和30之間,我們根據(jù)頁3中的指針p2找到頁8沐扳。
  3. 將28和頁8中的鍵值相比較潦闲,發(fā)現(xiàn)有匹配的鍵值28,鍵值28對應的用戶信息為(28,bv)迫皱。

區(qū)別:B樹相對于平衡二叉樹的不同是:每個節(jié)點包含的關鍵字增多了歉闰,特別是在B樹應用到數(shù)據(jù)庫中的時候,數(shù)據(jù)庫充分利用了磁盤塊的原理(磁盤數(shù)據(jù)存儲是采用塊的形式存儲的卓起,每個塊的大小為4K和敬,每次IO進行數(shù)據(jù)讀取時,同一個磁盤塊的數(shù)據(jù)可以一次性讀取出來)把節(jié)點大小限制和充分使用在磁盤快大小范圍戏阅;把樹的節(jié)點關鍵字增多后樹的層級比原來的二叉樹少了昼弟,減少數(shù)據(jù)查找的次數(shù)和復雜度。

相同數(shù)量的key在B-Tree中生成的節(jié)點要遠遠少于二叉樹中的節(jié)點奕筐,相差的節(jié)點數(shù)量就等同于磁盤IO的次數(shù)舱痘。這樣到達一定數(shù)量后,性能的差異就顯現(xiàn)出來了离赫。

B+樹(B+Tree)

概念

B+樹是B樹的一個進化芭逝,相對于B樹來說B+樹更充分得利用了節(jié)點的空間,讓查詢速度更加穩(wěn)定渊胸,其速度完全接近于二分法查找旬盯。結構如下:

[圖片上傳失敗...(image-fd3493-1648794941453)]

為什么說B+樹查找的效率要比B樹更高、更穩(wěn)定翎猛;我們先看看兩者的區(qū)別:

  1. B+樹的非葉子節(jié)點不保存數(shù)據(jù)胖翰,只進行數(shù)據(jù)索引(關鍵字記錄的指針),這樣使得B+樹每個非葉子節(jié)點所能保存的關鍵字大大增加切厘;
  2. B+樹葉子節(jié)點保存了父節(jié)點的所有關鍵字記錄的指針萨咳,所有數(shù)據(jù)地址必須要到葉子節(jié)點才能獲取到。所以每次數(shù)據(jù)查詢的次數(shù)都一樣疫稿;
  3. B+樹葉子節(jié)點的關鍵字從小到大有序排列培他,左邊結尾數(shù)據(jù)都會保存右邊節(jié)點開始數(shù)據(jù)的指針;
  4. B+樹非葉子節(jié)點的子節(jié)點數(shù)=關鍵字數(shù);

特點

  1. B+樹的層級更少:相較于B樹而克,B+每個非葉子節(jié)點存儲的關鍵字數(shù)更多靶壮,樹的層級更少所以查詢數(shù)據(jù)更快怔毛;
  2. B+樹查詢速度更穩(wěn)定:B+所有關鍵字數(shù)據(jù)地址都存在葉子節(jié)點上员萍,所以每次查找的次數(shù)都相同所以查詢速度要比B樹更穩(wěn)定;
  3. B+樹天然具備排序功能:B+樹所有的葉子節(jié)點數(shù)據(jù)構成了一個有序鏈表,在查詢大小區(qū)間的數(shù)據(jù)時候更方便拣度,數(shù)據(jù)緊密性很高碎绎,緩存的命中率也會比B樹高螃壤。
  4. B+樹全節(jié)點遍歷更快:B+樹遍歷整棵樹只需要遍歷所有的葉子節(jié)點即可,而不需要像B樹一樣需要對每一層進行遍歷筋帖,這有利于數(shù)據(jù)庫做全表掃描奸晴。

B樹相對于B+樹的優(yōu)點是:如果經常訪問的數(shù)據(jù)離根節(jié)點很近,而B樹的非葉子節(jié)點本身存有關鍵字其數(shù)據(jù)的地址日麸,所以這種數(shù)據(jù)檢索的時候會要比B+樹快寄啼。

根據(jù)上圖我們來看下B+樹和B樹有什么不同:

  1. B+Tree 非葉子節(jié)點上是不存儲數(shù)據(jù)的,僅存儲鍵值代箭,數(shù)據(jù)存儲在同一層的葉節(jié)點墩划,而B-Tree節(jié)點中不僅存儲鍵值,也會存儲數(shù)據(jù)嗡综。之所以這么做是因為在數(shù)據(jù)庫中頁的大小是固定的乙帮,innodb中頁的默認大小是16KB。如果不存儲數(shù)據(jù)极景,那么就會存儲更多的鍵值察净,相應的樹的階數(shù)(節(jié)點的子節(jié)點樹)就會更大,樹就會更矮更胖盼樟,如此一來我們查找數(shù)據(jù)進行磁盤的IO次數(shù)有會再次減少氢卡,數(shù)據(jù)查詢的效率也會更快。另外晨缴,B+Tree的階數(shù)是等于鍵值的數(shù)量的异吻,如果B+Tree一個節(jié)點可以存儲1000個鍵值,那么3層B+樹可以存儲1000×1000×1000=10億個數(shù)據(jù)喜庞。一般根節(jié)點是常駐內存的诀浪,所以一般我們查找10億數(shù)據(jù),只需要2次磁盤IO延都。
  2. 因為B+Tree索引的所有數(shù)據(jù)均存儲在葉子節(jié)點雷猪,而且數(shù)據(jù)是按照順序排列的。那么B+樹使得范圍查找晰房,排序查找求摇,分組查找以及去重查找變得異常簡單。而B-Tree 因為數(shù)據(jù)分散在各個節(jié)點殊者,要實現(xiàn)這一點是很不容易的与境。

B+Tree 中各個頁之間是通過雙向鏈表連接的,葉子節(jié)點中的數(shù)據(jù)是通過單向鏈表連接的猖吴。

其實上面的B-Tree也可以對各個節(jié)點加上鏈表摔刁。其實這些不是它們之前的區(qū)別,是因為在mysql的innodb存儲引擎中海蔽,索引就是這樣存儲的共屈。也就是說上圖中的B+Tree索引就是innodb中B+Tree索引真正的實現(xiàn)方式绑谣,準確地說應該是聚集索引。

通過上圖可以看到拗引,在innodb中借宵,數(shù)據(jù)頁之間通過雙向鏈表連接以及葉子節(jié)點中數(shù)據(jù)之間通過單向鏈表連接的方式可以找到表中所有的數(shù)據(jù)。

注意:MyISAM中的B+樹索引實現(xiàn)與innodb中的略有不同矾削。在MyISAM中壤玫,B+樹索引的葉子節(jié)點并不存儲數(shù)據(jù),而是存儲數(shù)據(jù)的文件地址哼凯。

總結

B+Tree 結構是從二叉查找樹垦细,平衡二叉樹和B-Tree這三種數(shù)據(jù)結構演化來的,他們之前的區(qū)別上面已經介紹過挡逼,現(xiàn)在大致的總結下括改,如下:

1. 二叉查找樹是基于二分查找法來提高數(shù)據(jù)查找速度的二叉樹的數(shù)據(jù)結構,減少無關數(shù)據(jù)的檢索家坎,提升了數(shù)據(jù)檢索的速度嘱能。非葉子節(jié)點只能允許最多兩個子節(jié)點存在,每一個非葉子節(jié)點數(shù)據(jù)分布規(guī)則為左邊的子節(jié)點小當前節(jié)點的值虱疏,右邊的子節(jié)點大于當前節(jié)點的值惹骂,每個節(jié)點只存儲一個鍵值和數(shù)據(jù)的。

2. 平衡二叉樹滿足二叉查找樹特性的基礎上做瞪,如不是空樹对粪,任何一個結點的左子樹與右子樹都是平衡二叉樹,并且高度之差的絕對值不超過 1装蓬。

3. B-TreeB和平衡二叉樹不同著拭,B-Tree屬于多叉樹又名平衡多路查找樹, B-Tree相對于平衡二叉樹牍帚,每個節(jié)點存儲了更多的鍵值(key)和數(shù)據(jù)(data)儡遮,并且每個節(jié)點擁有更多的子節(jié)點。

4. B+Tree和B-Tree不同暗赶,B+Tree在非葉子節(jié)點上鄙币,不保存數(shù)據(jù),只存儲鍵指針蹂随,能存儲更多的鍵值十嘿,相應的樹的階數(shù)(節(jié)點的子節(jié)點樹)就會更大,樹就會更矮更胖岳锁,如此一來我們查找數(shù)據(jù)進行磁盤的IO次數(shù)有會再次減少绩衷,數(shù)據(jù)查詢的效率也會更快。并且B+樹索引的所有數(shù)據(jù)均存儲在葉子節(jié)點,而且數(shù)據(jù)是按照順序排列的唇聘。那么B+Tree使得范圍查找版姑,排序查找柱搜,分組查找以及去重查找變得異常簡單迟郎。

</article>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市聪蘸,隨后出現(xiàn)的幾起案子宪肖,更是在濱河造成了極大的恐慌,老刑警劉巖健爬,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件控乾,死亡現(xiàn)場離奇詭異,居然都是意外死亡娜遵,警方通過查閱死者的電腦和手機蜕衡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來设拟,“玉大人慨仿,你說我怎么就攤上這事∧呻剩” “怎么了镰吆?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長跑慕。 經常有香客問我万皿,道長,這世上最難降的妖魔是什么核行? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任牢硅,我火速辦了婚禮,結果婚禮上芝雪,老公的妹妹穿的比我還像新娘唤衫。我一直安慰自己,他們只是感情好绵脯,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布佳励。 她就那樣靜靜地躺著,像睡著了一般蛆挫。 火紅的嫁衣襯著肌膚如雪赃承。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天悴侵,我揣著相機與錄音瞧剖,去河邊找鬼。 笑死,一個胖子當著我的面吹牛抓于,可吹牛的內容都是我干的做粤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼捉撮,長吁一口氣:“原來是場噩夢啊……” “哼怕品!你這毒婦竟也來了?” 一聲冷哼從身側響起巾遭,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤肉康,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后灼舍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吼和,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年骑素,在試婚紗的時候發(fā)現(xiàn)自己被綠了炫乓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡献丑,死狀恐怖末捣,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情阳距,我是刑警寧澤塔粒,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站筐摘,受9級特大地震影響卒茬,放射性物質發(fā)生泄漏。R本人自食惡果不足惜咖熟,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一圃酵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧馍管,春花似錦郭赐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至罗捎,卻和暖如春观谦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背桨菜。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工豁状, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捉偏,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓泻红,卻偏偏與公主長得像夭禽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子谊路,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內容