尬談對B+樹的我的理解

Today is the first day of the rest of your life. 
今天是你餘下人生的第一天。

前言

金三銀四,求職者愈來愈活躍,面試官問問題角度愈來愈刁鑽。一言不合就問底層實現。你們都知道MySQL索引的實現用到了B+樹,本文主要是分享了對B+樹的一點我的理解。面試

爲何MySQL的索引要用B+樹?

衆所周知,查找效率比較高的數據結構有不少,呢爲何要用B+樹呢?先簡單分析一下查詢效率比較高的幾種數據結構。redis

散列表

散列表的查詢性能很好,時間複雜度是 O(1)。可是,散列表不能支持按照區間快速查找數據。算法

跳錶

跳錶是在鏈表之上加上多層索引構成的。它支持快速地插入、查找、刪除數據,時間複雜度是 O(logn)。而且,跳錶也支持按照區間快速地查找數據。只須要定位到區間起點值對應在鏈表中的結點,而後從這個結點開始,順序遍歷鏈表,直到區間終點對應的結點爲止,這期間遍歷獲得的數據就是知足區間值的數據。mongodb

ps:redis的有序集合就是跳錶+散列表構建的

看着好像跳錶也能夠知足索引的要求。可能由於先有B+樹後有的跳錶,因此才選的B+?數據庫

平衡二叉查找樹

平衡二叉查找樹查詢的性能高,時間複雜度是 O(logn)。並且,對樹進行中序遍歷,能夠獲得一個從小到大有序的數據序列,但這仍然不足以支持按照區間快速查找數據。緩存

而且須要考慮一下磁盤的IO,數據索引是存在磁盤上的,當使用索引的時候,會把索引加到內存中去,(內存的訪問速度完爆磁盤的訪問速度)當數據足夠大的時候,把索引完整的加入到內存當中,顯然不現實。數據結構

B樹

再來看B樹,B樹相比較平衡二叉查找樹,它叉開的比較多,算是多叉平衡查找樹。也就是說B樹的高度要低,叉要多。若是把二叉查找樹比作一我的,那麼這我的是又高又有瘦,B樹則是又矮又胖,某華真實寫照,扎心了。。。性能

ps:樹有多高,磁盤就讀寫多少次。還有mongodb的索引就用到了B。

B+樹

B樹和B+樹實際上是一種樹,先由B樹到B+樹層層遞進,逐步分析。
rest

B樹和B+樹的區別

B樹是一個自平衡的多叉查找樹。它有如下優勢:

  1. 保持鍵值有序,以順序遍歷
  2. 使用層次化的索引來最小化磁盤讀取
  3. 使用不徹底填充的塊來加速插入和刪除
  4. 經過優雅的遍歷算法來保持索引平衡
  5. 經過保證內部節點至少半滿來最小化空間浪費。
  6. 能夠處理任意數目的插入和刪除。

而B+樹至關於B樹的升級版,相對於B樹來講B+樹更充分的利用了節點的空間,讓查詢速度更加穩定,其速度徹底接近於二分查找(二分查找速度不解釋)。B+在基於B樹的基礎上又有以下優勢:

  1. B+樹的層級更少:B+樹每一個非葉子節點存儲的關鍵字數更多,樹的層級更少因此查詢數據更快;
  2. B+樹查詢速度更穩定:B+全部關鍵字數據地址都存在葉子節點上,因此每次查找的次數都相同因此查詢速度要比B樹更穩定;
  3. B+樹自然具有排序功能:B+樹全部的葉子節點數據構成了一個有序鏈表,在查詢大小區間的數據時候更方便,數據緊密性很高,緩存的命中率也會比B樹高。
  4. B+樹全節點遍歷更快:B+樹遍歷整棵樹只須要遍歷全部的葉子節點便可,,而不須要像B樹同樣須要對每一層進行遍歷,這有利於數據庫作全表掃描。

總結

正由於B+樹的這種特性,所以這種數據結構經常使用於文件系統跟數據庫索引中。它經過對每一個節點存儲個數的擴展,使得對連續的數據可以進行較快的定位和訪問,可以有效減小查找時間,提升存儲的空間局部性從而減小IO操做。cdn

B+樹的特色

  • 每一個節點中子節點的個數不能超過 m,也不能小於 m/2
  •  根節點的子節點個數能夠不超過 m/2,這是一個例外
  • m 叉樹只存儲索引,並不真正存儲數據,這個有點兒相似跳錶
  •  經過鏈表將葉子節點串聯在一塊兒,這樣能夠方便按區間查找
  •  通常狀況,根節點會被存儲在內存中,其餘節點存儲在磁盤中

end


您的點贊和關注是對我最大的支持,謝謝!
相關文章
相關標籤/搜索