MySQL數據庫中索引的數據結構是什麼?(B樹和B+樹的區別)

 

 

B樹(又叫平衡多路查找樹)

注意B-樹就是B樹,-只是一個符號。

B樹的性質(一顆M階B樹的特性如下)

1、定義任意非葉子結點最多隻有M個兒子,且M>2; 
2、根結點的兒子數爲[2, M]; 
3、除根結點以外的非葉子結點的兒子數爲[M/2, M]; 
4、每個結點存放至少M/2-1(取上整)和至多M-1個關鍵字;(至少2個關鍵字) 
5、非葉子結點的關鍵字個數=指向兒子的指針個數-1; 
6、非葉子結點的關鍵字:K[1], K[2], …, K[M-1];且K[i] < K[i+1]; 
7、非葉子結點的指針:P[1], P[2], …, P[M];其中P[1]指向關鍵字小於K[1]的子樹,P[M]指向關鍵字大於K[M-1]的子樹,其它P[i]指向關鍵字屬於(K[i-1], K[i])的子樹; 
8、所有葉子結點位於同一層;

 

B-樹的搜索,從根結點開始,對結點內的關鍵字(有序)序列進行二分查找,如果命中則結束,否則進入查詢關鍵字所屬範圍的兒子結點;重複,直到所對應的兒子指針爲空,或已經是葉子結點;

B-樹的特性:

1.關鍵字集合分佈在整顆樹中;

2.任何一個關鍵字出現且只出現在一個結點中;

3.搜索有可能在非葉子結點結束;

4.其搜索性能等價於在關鍵字全集內做一次二分查找;

 

B+樹

(1)簡介

B+樹是應文件系統所需而產生的一種B樹的變形樹(文件的目錄一級一級索引,只有最底層的葉子節點(文件)保存數據)非葉子節點只保存索引,不保存實際的數據,數據都保存在葉子節點中,這不就是文件系統文件的查找嗎?

我們就舉個文件查找的例子:有3個文件夾a、b、c, a包含b,b包含c,一個文件yang.c,a、b、c就是索引(存儲在非葉子節點), a、b、c只是要找到的yang.c的key,而實際的數據yang.c存儲在葉子節點上。

所有的非葉子節點都可以看成索引部分!

(2)B+樹的性質(下面提到的都是和B樹不相同的性質)

1、非葉子節點的子樹指針與關鍵字個數相同; 
2、非葉子節點的子樹指針p[i],指向關鍵字值屬於[k[i],k[i+1]]的子樹.(B樹是開區間,也就是說B樹不允許關鍵字重複,B+樹允許重複); 
3、爲所有葉子節點增加一個鏈指針; 
4、所有關鍵字都在葉子節點出現(稠密索引). (且鏈表中的關鍵字恰好是有序的); 
5、非葉子節點相當於是葉子節點的索引(稀疏索引),葉子節點相當於是存儲(關鍵字)數據的數據層; 
6、更適合於文件系統;

 

 

 

 

 

非葉子節點(比如5,28,65)只是一個key(索引),實際的數據存在葉子節點上(5,8,9)纔是真正的數據或指向真實數據的指針。

應用  

1、B和B+樹主要用在文件系統以及數據庫做索引,比如MySQL;(MySQL使用B+樹)

B/B+樹性能分析

n個節點的平衡二叉樹的高度爲H(即logn),而n個節點的B/B+樹的高度爲logt((n+1)/2)+1; 
若要作爲內存中的查找表,B樹卻不一定比平衡二叉樹好,尤其當m較大時更是如此。因爲查找操作CPU的時間在B-樹上是O(mlogtn)=O(lgn(m/lgt)),而m/lgt>1;所以m較大時O(mlogtn)比平衡二叉樹的操作時間大得多。因此在內存中使用B樹必須取較小的m。(通常取最小值m=3,此時B-樹中每個內部結點可以有2或3個孩子,這種3階的B-樹稱爲2-3樹)。

爲什麼說B+樹比B樹更適合數據庫索引?

1、 B+樹的磁盤讀寫代價更低:B+樹的內部節點並沒有指向關鍵字具體信息的指針,因此其內部節點相對B樹更小,如果把所有同一內部節點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多,一次性讀入內存的需要查找的關鍵字也就越多,相對IO讀寫次數就降低了。

2、B+樹的查詢效率更加穩定:由於非終結點並不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。

3、由於B+樹的數據都存儲在葉子結點中,分支結點均爲索引,方便掃庫,只需要掃一遍葉子結點即可,但是B樹因爲其分支結點同樣存儲着數據,我們要找到具體的數據,需要進行一次中序遍歷按序來掃,所以B+樹更加適合在區間查詢的情況,所以通常B+樹用於數據庫索引。

PS:我在知乎上看到有人是這樣說的,我感覺說的也挺有道理的:

他們認爲數據庫索引採用B+樹的主要原因是:B樹在提高了IO性能的同時並沒有解決元素遍歷的我效率低下的問題,正是爲了解決這個問題,B+樹應用而生。B+樹只需要去遍歷葉子節點就可以實現整棵樹的遍歷。而且在數據庫中基於範圍的查詢是非常頻繁的,而B樹不支持這樣的操作或者說效率太低。

 

 

今天看了幾篇文章,自己總結一下。

數據庫使用B+樹肯定是爲了提升查找效率。

但是具體如何提升查找效率呢?

查找數據,最簡單的方式是順序查找。但是對於幾十萬上百萬,甚至上億的數據庫查詢就很慢了。

所以要對查找的方式進行優化,熟悉的二分查找,二叉樹可以把速度提升到O(log(n,2)),查詢的瓶頸在於樹的深度,最壞的情況要查找到二叉樹的最深層,由於,每查找深一層,就要訪問更深一層的索引文件。在多達數G的索引文件中,這將是很大的開銷。所以,儘量把數據結構設計的更爲‘矮胖’一點就可以減少訪問的層數。在衆多的解決方案中,B-/B+樹很好的適合。B-樹定義具體可以查閱,簡而言之就是中間節點可以多餘兩個子節點,而且中間的元素可以是一個域。相比B-樹,B+樹的父節點也必須存在於子節點中,是其中最大或者最小元素,B+樹的節點只存儲索引key值,具體信息的地址存在於葉子節點的地址中。這就使以頁爲單位的索引中可以存放更多的節點。減少更多的I/O支出。因此,B+樹成爲了數據庫比較優秀的數據結構,MySQL中MyIsAM和InnoDB都是採用的B+樹結構。不同的是前者是非聚集索引,後者主鍵是聚集索引,所謂聚集索引是物理地址連續存放的索引,在取區間的時候,查找速度非常快,但同樣的,插入的速度也會受到影響而降低。聚集索引的物理位置使用鏈表來進行存儲。

 

參考鏈接:

https://www.2cto.com/net/201808/773535.html

https://www.cnblogs.com/tiancai/p/9024351.html

發佈了14 篇原創文章 · 獲贊 7 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章