Mysql索引結構,B+樹看這篇就夠了!

本文主要介紹MySQL的InnoDB搜索引擎的索引結構。文章從最初的全文檢索開始,經過Hash、二叉樹、平衡二叉樹、B樹到最後爲什麼選用B+樹作爲索引結構的路線介紹。文章涉及數據結構以及一些硬件知識,全文較長請耐心閱讀。

 介紹之前分享一個學習數據結構的優秀網站 Data Structure Visualizations 裏面提供了各種數據結構的動畫演示,打開網站配合文章你會得到驚奇的效果。

目錄

 全文檢索

 Hash結構

 二叉樹

 平衡二叉樹(AVL樹) 

 B樹 

 B+樹 


全文檢索

這種方式是在MySQL查詢時候全盤掃描。相當於一個大型圖書館裏面的書是雜亂無章的,想要查找一本書的時候需要從頭到尾的進行查詢一遍。這種是效率最低的方式時間複雜度爲O(n)。爲了優化增刪改查速度再此基礎上可以優化成Hash結構。

 Hash結構

爲了彌補全文檢索的缺點進一步優化索引結構爲Hash結構,這種結構可以通過Hash算法把要存儲的內容計算得出地址。在查找的時候可以同樣利用Hash算法計算得出的地址取出內容。Hash數據結構增刪改查時間複雜度爲O(1)。數據結構圖如下所示,存儲和取值可以在Hash動畫演示中操作。

Hash結構的優點在於對單一值的存儲和查詢比較快,但是我們都知道使用MySQL進行查詢很多的時候是進行的一個範圍的查找,對於這種情況的查詢Hash結構的時間複雜度從O(1)直接提高到了O(n)。所以MySQL的索引結構就演變成了樹結構。樹結構分爲二叉樹、二插平衡樹(AVL樹)、B樹、B+樹、紅黑樹等等。增、刪、改、查、排序和範圍的時間複雜度爲O(log2(n)。

 二叉樹

 所謂的二叉樹就是指的每個結點最多有兩個子樹的樹結構。二叉樹概念介紹 有需要的點擊查看,本文重點介紹實戰內容概念性的不加以贅述。二叉樹結構圖如下圖,動態操作可以在二叉樹動畫演示中模擬。

                                                       

二叉樹主要的特點:

  1. 一個節點只能有兩個子節點,一個節點度不能超過2;
  2. 左子節點小於本節點,右字節點大於本節點;

                                                                       

檢索原理:對於此二叉樹的查找發現,查找深度爲1的次數爲1、查找深度爲2的次數爲2、深度爲N的查找次數爲N;因此此樹的平均查找次數爲(1+2+2+3+3+3)/6 = 2.3(次)。

通過上述的檢索原理可知,二叉樹有2個缺點。當二叉樹中每次新插入的值都比原樹中的節點值大或者小就會形成下圖的右傾或者左傾的樹形結構從樹形結構變成了鏈表。

                                                        

這種左傾或者右傾的二叉樹在查找的時候時間複雜度從O(log2(n))變成了O(n)。

第二個缺點是當出現下面的情況的時候,數據結構變成了鏈表+樹的結構對於增刪改查等操作又增加了困難。

                                                

鑑於以上問題對二叉樹有進一步的進行了優化從二叉樹變成了平衡二叉樹。

平衡二叉樹(AVL樹) 

 它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。平衡二叉樹的常用實現方法有紅黑樹AVL替罪羊樹Treap伸展樹等。爲了防止想二叉樹一樣的左傾或者右傾的情況發生,平衡二叉樹引入了旋轉操作其中包括左旋和右旋,二叉樹的結構圖如圖所示,演示動畫可以在平衡二叉樹演示模擬。

                                                    

平衡二叉樹有一個缺點就是隨着數據量增大樹的高度也隨之變高。對樹進行操作的時候增加了IO的次數同樣會變慢。爲了解決這個問題就需要增加的樹的節點降低樹的高度從“瘦高”變成“矮胖”從而減少磁盤的IO次數,繼而引入的B樹。

B樹 

B樹又稱B-樹、二三樹。 B樹的結構圖如圖所示,樹的增刪改查操作可以用B樹的動畫模擬動畫模擬。

                                                            

瞭解完B樹的數據結構之後我們來了解一下B樹的檢索原理:首先數據庫的索引是存在磁盤上的,如果數據量很大的情況下數據庫的索引也會很大,可能超過幾個G。當我們利用索引查詢數據的時候是不可能一次加載所有的索引進內存,計算機只能逐一加載每一個磁盤頁(這裏引入楓暘一生博主的一篇文章介紹硬件),因爲磁盤頁是對應着索引樹的每一個節點。Innodb默認磁盤頁大小16K,Innodb每次加載數據都是以頁爲單位。sql語句查看頁大小SHOW GLOBAL STATUS LIKE 'Innodb_page_size';

             

接下來我們瞭解一下B樹的檢索原理:

      

每一個節點佔用一塊磁盤空間,一個節點上有兩個升序排序的關鍵字和三個指向子樹根節點的指針,指針存儲的是子節點所在的磁盤塊的地址。

模擬查找關鍵字29的過程:

根據根節點找到磁盤塊1,讀入內存。【磁盤 I/O操作第1次】

比較關鍵字29在區間(17,35)找到磁盤塊1的指針P2.

根據P2指針找到磁盤塊3,讀入內存。【磁盤 I/O操作第2次】

比較關鍵字29在區間(26,30),找到磁盤塊3的指針P2。

根據P2指針找到磁盤塊8,讀入內存。【磁盤 I/O操作第3次】

在磁盤塊8中的關鍵字列表找到關鍵字29。

分析上面過程,發現需要3的磁盤的I/O操作和3次的內存查找操作。由於內存中的關鍵字是一個有序表結構,可以利用二分法查找提高效率。I/O操作是影響整個BTree查找效率的決定因素。BTree相對於AVL樹縮減了節點個數,使每次磁盤I/O取到內存的數據都發揮了作用,從而提高了查詢效率。其實到B樹的時候已經優化的很好了,可是這羣“變態”又進行了優化引入了B+樹。

B+樹 

B+樹的結構如圖:

 

 插入的動畫演示地址B+樹動畫演示

我們可以看到圖中的所有Data信息都移動到葉子節點中,而且節點和節點之間都會有一個指針指向,這個也是B+樹的核心點。B+樹相當於樹形結構+鏈表,把各種數據結構的優點整合(可以類比JAVA8版本的HashMap的數組+鏈表+紅黑樹)這樣可以大大的提高範圍查詢 效率,也方便遍歷整個樹。

B+樹特點總結爲:

  1. 非葉子節點不在存儲數據,數據只存儲在同一層的葉子節點上;
  2. 葉子之間增加了鏈表,獲取所有節點不再需要中序遍歷

說完特點和結構之後再聊聊B+樹的檢索原理,由於B+樹的非葉子節點智慧存儲鍵值信息,假設每個磁盤塊能存儲4個鍵值及指針信息,則變成B+樹後其結構如下圖所示:

         

B樹結構圖中可以看到每個節點中不僅包含數據的key值,還有data值。而且每一頁的存儲空間是有限的,如果data數據較大時會導致每個節點(即每一頁)能存儲的key的數量很小,當存儲的數據量很大時會導致B樹的深度較大,增大查詢時的磁盤I/O次數進而影響查詢效率。

但在B+樹中,所有的數據記錄節點都是按照鍵值大小順序存放在同一層的葉子節點上,而非葉子節點只存儲key值信息,這樣可以加大每個節點存儲的key值數量,降低B+樹的高度。

1、InnoDB存儲引擎的最小存儲單元是頁,頁可以用戶存放數據也可以用於存放鍵值+指針;

2、索引組織表通過非葉子節點的二分查找法以及指針確定數據在哪個頁中,首先找到跟頁繼而在去數據頁中查找到需要的數據;

B+樹算法:通過繼承了B樹的特徵,B+樹相比B樹,新增葉子節點與非葉子節點的關係。葉子節點中包含數據和鍵值,非葉子節點中值包含鍵值和子節點引用,不包含數據。通過非葉子節點查詢葉子節點獲取對應的數據,所有相鄰的葉子節點包含非葉子節點使用鏈表進行結合,葉子節點是順序排序並且相鄰節點有順序引用的關係。

 以上就是個人對InnoDB中B+樹索引數據結構以及演變過程的介紹,歡迎批評指正。MySQL的搜索引擎還有MyISAM搜索引擎本文不作爲重點介紹。喜歡的朋友可以關注,後續會更新數據庫事務、鎖等技術。

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章