B樹
一、基本原理
B樹是一種查找樹,它最初啟發於二叉查找樹。
二叉查找樹的特點是每個非葉節點都只有兩個孩子節點。然而這種做法會導致當數據量非常大時,二叉查找樹的深度過深,搜索算法自根節點向下搜索時,需要訪問的節點也就變的相當多。
如果這些節點存儲在外存儲器中,每訪問一個節點,相當於就是進行了一次I/O操作,隨着樹高度的增加,頻繁的I/O操作一定會降低查詢的效率。
磁盤讀取信息:
找到存儲這個數據所對應的磁盤頁面,這個過程是機械化的過程,需要依靠磁臂的轉動,找到對應磁道,所以耗時長。
讀取數據進內存,並實施運算,這是電子化的過程,相當快。
對於外存儲器的信息讀取最大的時間消耗在於尋找磁盤頁面。那么一個基本的想法就是能不能減少這種讀取的次數,在一個磁盤頁面上,多存儲一些索引信息。
B樹的基本邏輯就是這個思路,它要改二叉為多叉,每個節點存儲更多的指針信息,以降低I/O操作數。
二、基本結構
1. B樹的定義
這里用最小度t來定義B樹。一棵最小度為t的B樹是滿足如下四個條件的平衡多叉樹:
-
每個節點最多包含2t−1個關鍵字;除根節點外的每個節點至少有t−1個關鍵字(t≤2),根節點至少有一個關鍵字;
-
一個節點u中的關鍵字按非降序排列:u.key1≤u.key2≤…u.keyn;
-
每個節點的關鍵字對其子樹的范圍分割。設節點u有n+1個指針,指向其n+1棵子樹,指針為u.p1,…u.pn,關鍵字k為u.pi所指的子樹中的關鍵字,有k1≤u.key1≤k2≤u.key2…成立;
-
所有葉子節點具有相同的深度,即樹的高度h。這表明B樹是平衡的。
一個標准的B樹如下圖:
三、搜索算法
一棵已經建立好的B樹如下圖所示,我們的目的是查找關鍵字為29的文件:
先簡單對上圖說明一下:
-
圖中的小紅方塊表示對應關鍵字所代表的文件的存儲位置,實際上可以看做是一個地址,比如根節點中17旁邊的小紅塊表示的就是關鍵字17所對應的文件在硬盤中的存儲地址。
-
P是指針,不用多說了,需要注意的是:指針,關鍵字,以及關鍵字所代表的文件地址這三樣東西合起來構成了B樹的一個節點,這個節點存儲在一個磁盤塊上
下面,看看搜索關鍵字的29的文件的過程:
-
從根節點開始,讀取根節點信息,根節點有2個關鍵字:17和35。因為17 < 29 < 35,所以找到指針P2指向的子樹,也就是磁盤塊3(1次I/0操作)
-
讀取當前節點信息,當前節點有2個關鍵字:26和30。26 < 29 < 30,找到指針P2指向的子樹,也就是磁盤塊8(2次I/0操作)
-
讀取當前節點信息,當前節點有2個關鍵字:28和29。找到了!(3次I/0操作)
由上面的過程可見,同樣的操作,如果使用平衡二叉樹,那么需要至少4次I/O操作,B樹比之二叉樹的這種優勢,還會隨着節點數的增加而增加。
另外,因為B樹節點中的關鍵字都是排序好的,所以,在節點中的信息被讀入內存之后,可以采用二分查找這種快速的查找方式,更進一步減少了讀入內存之后的計算時間。
B+樹
B+樹的定義
B+樹是B樹的一種變形,它更適合實際應用中操作系統的文件索引和數據庫索引。
定義如下:(這里使用階數m來定義B+樹)
除根節點外的內部節點,每個節點最多有m個關鍵字,最少有⌈m/2⌉個關鍵字。其中每個關鍵字對應一個子樹(也就是最多有m棵子樹,最少有⌈m/2⌉棵子樹);
根節點要么沒有子樹,要么至少有2棵子樹;
所有的葉子節點包含了全部的關鍵字以及這些關鍵字指向文件的指針
所有葉子節點中的關鍵字按大小順序排列
相鄰的葉子節點順序鏈接(相當於是構成了一個順序鏈表)
所有葉子節點在同一層
比如,下圖就是一個非常典型的B+樹的例子。
B+樹和B樹相比,主要的不同點在以下3項:
(1)B+樹的非葉子節點不保存關鍵字記錄的指針,這樣使得B+樹每個節點所能保存的關鍵字大大增加;
(2)B+樹葉子節點保存了父節點的所有關鍵字和關鍵字記錄的指針,每個葉子節點的關鍵字從小到大鏈接;
(3)B+樹的根節點關鍵字數量和其子節點個數相等;
(4)B+的非葉子節點只進行數據索引,不會存實際的關鍵字記錄的指針,所有數據地址必須要到葉子節點才能獲取到,所以每次數據查詢的次數都一樣;
根據B+樹的結構,我們可以發現B+樹相比於B樹,在文件系統,數據庫系統當中,更有優勢,原因如下:
B+樹的磁盤讀寫代價更低
B+樹的內部結點並沒有指向關鍵字具體信息的指針。因此其內部結點相對B樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那么盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的需要查找的關鍵字也就越多。相對來說I/O讀寫次數也就降低了。
B+樹的查詢效率更加穩定
由於內部結點並不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。
B+樹更有利於對數據庫的掃描
B樹在提高了磁盤IO性能的同時並沒有解決元素遍歷的效率低下的問題,而B+樹只需要遍歷葉子節點就可以解決對全部關鍵字信息的掃描,所以對於數據庫中頻繁使用的range query,B+樹有着更高的性能。
參考:https://blog.csdn.net/guoziqing506/article/details/64122287