我們已經知道他們兩是mysql索引的資料結構,為什麼要使用這種資料結構呢?我們知道記憶體讀取效率遠遠高於磁碟io的效率,當資料量大而不能完全存放於記憶體時,只能依靠磁碟了,一次存放於磁碟頁中,每個磁碟頁對應乙個樹的節點。也就是說只要我們能減少磁碟io的次數,那麼查詢效率就會顯著提高。如何減少?
b樹就是通過降低樹的深度,將二叉樹的「瘦高」變成「矮胖」:
1.每個節點儲存多個元素。
2.採用多叉樹。
這裡先說下階和度的區別:
度數:在樹中,每個節點的子節點(子樹)的個數就稱為該節點的度(degree)。
階數:(order)階定義為乙個節點的子節點數目的最大值。(自帶最大值屬性)
m階的b樹的規則:
根節點至少2個子樹
每個節點最多有m個子樹
每個中間節點都包含k-1個元素和k個孩子,其中ceil(m/2)<=k<=m(ceil向上取最大整數)
每個葉子節點的元素範圍:[ceil(m/2)-1,m-1]
所有的葉子節點都在同一層
每個節點中的元素從小到大排列,節點當中k-1個元素正好是k個孩子包含的元素的值域劃分
每個節點不僅有索引的值還都儲存了衛星資料,b+樹不同
衛星資料:指向資料庫的記錄(如:資料庫中的行)類似於指標指向記錄
示例:3階b樹(實際有很多節點沒有表示出來)
查詢:
上圖為例查詢5
第一次磁碟io:在記憶體中定位(與17、35比較),比17小,左子樹; 第二次磁碟io:在記憶體中定位(與8、12比較),比8小,左子樹; 第三次磁碟io:在記憶體中定位(與3、5比較),找到5,終止。
整個過程中,我們可以看出:比較的次數並不比二叉查詢樹少,尤其適當某一節點中的資料很多時,但是磁碟io的次數卻是大大減少。比較是在記憶體中進行的,相比於磁碟io的速度,比較的耗時幾乎可以忽略。所以當樹的高度足夠低的話,就可以極大的提高效率。相比之下,節點中的元素多點也沒關係,僅僅是多了幾次記憶體互動而已,只要不超過磁碟頁的大小即可。
b+樹是b樹的變種,有著比b樹更高的查詢效率。一般用作於mysql索引。
m階b+樹的規則:
有k個子樹的中間節點包含有k個元素(b樹中是k-1個元素),每個元素不儲存資料,只用來索引,所有資料都儲存在葉子節點。
所有的葉子結點中包含了全部元素的資訊,及指向含這些元素記錄的指標,且葉子結點本身依關鍵字的大小自小而大順序鏈結,形成乙個有序的鍊錶。
所有的中間節點元素都同時存在於子節點,在子節點元素中是最大(或最小)元素。
示例:
b樹:
b+樹:
通過比較我們可以發現:b樹中每個元素都會存放衛星資料,那麼就會有這樣乙個缺點:同等資料下,b+樹的磁碟頁存放的節點會比b樹的多,也就是說b+樹會比b樹更「矮胖」。
通過單元素查詢和範圍查詢來比較分析。
按照上圖比如查詢數字3,不管b還是b+都會經歷3次磁碟io,看起來似乎都是一樣的,但是b+樹的磁碟頁存放的節點比b樹多,一旦資料量大了之後會明顯降低磁碟io。
b+樹比b樹查詢更穩定:b樹要查詢到匹配元素(最好情況是根節點,最壞情況是葉子節點),b+樹無論匹配元素在哪都必須查詢到葉子節點(資料存放在葉子節點)。
在實際應用場景中,一般查詢的都是多條資料,有可能會需要跨節點遍歷查詢
b樹的範圍查詢需要不斷的中序遍歷。首先二分查詢到範圍下限,在不斷的通過中序遍歷,直到查詢到範圍上限,比較耗時繁瑣。
b+樹相比較於b樹就簡單許多,首先通過二分查詢,找到範圍下限,然後通過葉子結點的鍊錶順序遍歷,直至範圍上限,效率很高。
b樹的範圍查詢:
b+樹的範圍查詢:
資料結構 四 B樹 B 樹 B 樹 B 樹
b樹 即二叉搜尋樹 1.所有非葉子結點至多擁有兩個兒子 left和right 2.所有結點儲存乙個關鍵字 3.非葉子結點的左指標指向小於其關鍵字的子樹,右指標指向大於其關鍵字的子樹 如 b樹的搜尋,從根結點開始,如果查詢的關鍵字與結點的關鍵字相等,那麼就命中 否則,如果查詢關鍵字比結點關鍵字小,就進...
資料結構之B樹 B 樹 B 樹 B 樹
b 樹b 樹 b b b 樹是為了磁碟或其它儲存裝置而設計的一種平衡多路查詢樹 相對於二叉,b樹每個內節點有多個分支 與紅黑樹相比,在相同的的節點的情況下,一顆b樹的高度遠遠小於紅黑樹的高度.b樹上操作的時間通常由訪問磁碟的時間和cpu計算時間這兩部分構成,而cpu的速度非常快,所以b樹的操作效率取...
資料結構 B樹 B 樹 B 樹 B 概念
b樹 即二叉搜尋樹 1.所有非葉子結點至多擁有兩個兒子 left和right 2.所有結點儲存乙個關鍵字 3.非葉子結點的左指標指向小於其關鍵字的子樹,右指標指向大於其關鍵字的子樹 如 b樹的搜尋,從根結點開始,如果查詢的關鍵字與結點的關鍵字相等,那麼就命中 否則,如果查詢關鍵字比結點關鍵字小,就進...