B-樹,這裏的 B 表示 balance( 平衡的意思),B-樹是一種多路自平衡的搜索樹
它相似普通的平衡二叉樹,不一樣的一點是B-樹容許每一個節點有更多的子節點。下圖是 B-樹的簡化圖.html
B-樹有以下特色:mysql
全部鍵值分佈在整顆樹中;linux
任何一個關鍵字出現且只出如今一個結點中;git
搜索有可能在非葉子結點結束;github
在關鍵字全集內作一次查找,性能逼近二分查找;算法
B+樹是B-樹的變體,也是一種多路搜索樹, 它與 B- 樹的不一樣之處在於:sql
全部關鍵字存儲在葉子節點出現,內部節點(非葉子節點並不存儲真正的 data)數據庫
爲全部葉子結點增長了一個鏈指針數據結構
簡化 B+樹 以下圖性能
紅黑樹等數據結構也能夠用來實現索引,可是文件系統及數據庫系統廣泛採用B-/+Tree做爲索引結構。MySQL 是基於磁盤的數據庫系統,索引每每以索引文件的形式存儲的磁盤上,索引查找過程當中就要產生磁盤I/O消耗,相對於內存存取,I/O存取的消耗要高几個數量級,索引的結構組織要儘可能減小查找過程當中磁盤I/O的存取次數。爲何使用B-/+Tree,還跟磁盤存取原理有關。
因爲磁盤的存取速度與內存之間鴻溝,爲了提升效率,要儘可能減小磁盤I/O.磁盤每每不是嚴格按需讀取,而是每次都會預讀,磁盤讀取完須要的數據,會順序向後讀必定長度的數據放入內存。而這樣作的理論依據是計算機科學中著名的局部性原理:
當一個數據被用到時,其附近的數據也一般會立刻被使用 程序運行期間所須要的數據一般比較集中
因爲磁盤順序讀取的效率很高(不須要尋道時間,只需不多的旋轉時間),所以對於具備局部性的程序來講,預讀能夠提升I/O效率.預讀的長度通常爲頁(page)的整倍數。
MySQL(默認使用InnoDB引擎),將記錄按照頁的方式進行管理,每頁大小默認爲16K(這個值能夠修改).linux 默認頁大小爲4K
實際實現B-Tree還須要使用以下技巧:
每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁裏,加之計算機存儲分配都是按頁對齊的,就實現了一個結點只需一次I/O。
假設 B-Tree 的高度爲 h,B-Tree中一次檢索最多須要h-1次I/O(根節點常駐內存),漸進複雜度爲O(h)=O(logdN)O(h)=O(logdN)。通常實際應用中,出度d是很是大的數字,一般超過100,所以h很是小(一般不超過3)。
而紅黑樹這種結構,h明顯要深的多。因爲邏輯上很近的節點(父子)物理上可能很遠,沒法利用局部性,因此紅黑樹的I/O漸進複雜度也爲O(h),效率明顯比B-Tree差不少。
B+樹更適合外部存儲,因爲內節點無 data 域,一個結點能夠存儲更多的內結點,每一個節點能索引的範圍更大更精確,也意味着 B+樹單次磁盤IO的信息量大於B-樹,I/O效率更高。
Mysql是一種關係型數據庫,區間訪問是常見的一種狀況,B+樹葉節點增長的鏈指針,增強了區間訪問性,可以使用在範圍區間查詢等,而B-樹每一個節點 key 和 data 在一塊兒,則沒法區間查找。
個人博客: http://ygmyth.github.io
[1] 姜承堯 著;MySQL技術內幕-InnoDB存儲引擎;機械工業出版社,2013
[2] MySQL索引背後的數據結構及算法原理 http://blog.codinglabs.org/articles/theo...
[3] 從 MongoDB 及 Mysql 談B/B+樹 http://blog.csdn.net/wwh578867817/articl...