MySQL Index 之 B+Tree數據結構

MySQL中90%的慢Sql都可以通過索引來得到優化,爲什麼索引可以使Sql變的更快,我們需要先了解下MySQL InnoDB都有哪些索引。

按規則分類:

Hash索引

Memory引擎默認

USING HASH

BTREE索引

InnoDB引擎默認B+Tree

USING BTREE

按類型分類:

主鍵

也叫聚集索引,不允許有Null值

唯一索引

同主鍵,但允許有Null值

二級索引

輔助索引

全文索引

MySQL5.6以後才支持,且只能是char、varchar,text字符類型纔可以創建全文索引

複合索引

多列聯合的索引,可以是主鍵,也可以是輔助索引

數據結構:

不管哪種索引,都是一種數據結構。

哈希表

字段值通過Hash算法得出的Hash碼,Hash索引中存儲的即Hash碼

二叉樹

每個節點包含左右指針、鍵值、存儲地址,左子樹的鍵值小於根的鍵值,右子樹的鍵值大於根的鍵值

平衡二叉樹

每個節點包含左右指針、鍵值、存儲地址,左子樹的鍵值小於根的鍵值,右子樹的鍵值大於根的鍵值,兩個子樹的高度最大差爲1

BTree

非葉子節點也存儲數據,無雙向鏈指針

B+Tree

只有葉子節點存儲數據,有雙向鏈指針

哈希表

哈希索引就是採用一定的哈希算法,把鍵值換算成新的哈希值,同時在哈希表中保存指向每個數據行的指針。檢索時不需要類似B+Tree那樣從根節點到葉子節點逐級查找,只需一次哈希算法即可定位到相應的位置,速度非常快。但優勢只適用於鍵值唯一的等值查詢。

二叉樹與平衡二叉樹

二叉樹:可以任意地構造,高度越大效率越低,以下6個值平均查找次數爲(1+2+3+4+5+5)/ 6 = 3.3 次IO。

平衡二叉樹:平衡二叉樹簡稱平衡樹,是由Adelson-Velskii和Landis於1962年首先提出的,所以又稱爲AVL樹。在符合二叉樹的條件下,還滿足任何節點的兩個子樹的高度最大差爲1,以下6個值平均查找次數(1+2+2+3+3+3)/ 6 = 2.3 次IO。

缺點:

大量刪除、新增會導致頻繁旋轉;

實際運用較少,主要用於數據結構研究。

BTree:

BTree是爲磁盤存儲而專門設計的一類平衡搜索樹,文件系統和數據庫系統一般都採用BTree的數據結構,主要爲提升排序和檢索的效率。

由於BTree的所有節點都存儲數據,這就限制了BTree節點擁有孩子節點個數,如果數據量特別大,會導致樹的高度變高,IO就會增多。

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

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

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

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

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

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

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

分析上面過程,發現需要3次磁盤I/O操作,和3次內存。

但如果我們想進行範圍查找,查詢10~79之間的數據,就需要從跟節點一個一個往下查,範圍跨度越大,則磁盤IO的次數就越多,性能越差。因此在BTree的基礎上就有了B+Tree。

B+Tree:

B+Tree是在BTree基礎上的一種優化,使其更適合實現外存儲索引結構,InnoDB存儲引擎就是用B+Tree實現其索引結構。

B+Tree相對於BTree有幾點不同:

  1. 非葉子節點只存儲鍵值信息。

  2. 所有葉子節點之間都有一個雙向鏈指針。

  3. 數據記錄都存放在葉子節點中。

     

這樣索引樹不用太高,就能滿足需要對數據的檢索需求,使查詢更快速,例如:

定義一棵B+Tree,高度h = 3;

我們知道MySQL InnoDB默認數據頁大小爲16k;


 

MySQL root@[mysql]>show global status like 'Innodb_page_size';+------------------+-------+| Variable_name | Value |+------------------+-------+| Innodb_page_size | 16384 |+------------------+-------+

假設字符集爲utf8,在一個int字符類型的字段加索引(int固定佔4個字節);

一個Page除去頁號、頁類型等10個字節(如下圖);

非葉子節點存儲鍵值(扇出係數) = 16384 / (4+10) = 1170 個Key;

所以在高度h=3時,索引裏檢索的key爲:1170^3 ≈ 16億,即只需要3次IO就能檢索16億的key。

如果是varchar等其他字符類型,佔用Page字節較大,非葉子節點存儲鍵值會減少,相應可檢索的key也減少,樹高度就有可能會升高,IO會就多一次,從而導致相對變慢。一般2~4層高度大部分已經夠用了。

B+Tree主鍵索引:

InnoDB中主鍵索引的葉子節點的數據區域存儲的是數據記錄,輔助索引存儲的是主鍵值。

B+Tree輔助索引:

Innodb中的主鍵索引和實際數據時綁定在一起的,也就是說Innodb的一個表一定要有主鍵索引,如果一個表沒有手動建立主鍵索引,Innodb會查看有沒有唯一索引,如果有則選用唯一索引作爲主鍵索引,如果連唯一索引也沒有,則會默認建立一個隱藏的主鍵索引(用戶不可見)。另外,Innodb的主鍵索引要比MyISAM的主鍵索引查詢效率要高(少一次磁盤IO),並且比輔助索引也要高很多。

所以,我們在使用Innodb作爲存儲引擎時,我們最好:

  • 每個表都創建主鍵索引

  • 最好是int型作爲主鍵

  • 儘量根據主鍵查詢

 

 

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