Hash索引是MEMORY引擎默認使用的索引結構,也只有MEMORY引擎能夠顯式使用Hash索引,實際上就是HashTable,key-value結構。同時也是用拉鍊法解決hash衝突,這裏不展開討論。html
這裏須要注意的是HashTable的Value裏面並非直接存儲的單行數據而是存的是指針。mysql
若是咱們要了解B+樹,就必定要先了解B樹,B樹是爲磁盤等直接存儲的輔助存儲設備而設計的一種平衡搜索樹,它的節點能夠存儲多個關鍵字,而且它是一個多叉樹,一個B樹知足如下條件:算法
先解釋幾個詞:sql
定義:數據庫
如圖這是一個3階B樹 markdown
B樹的插入主要涉及三個步驟,查詢、插入、分裂。數據結構
B樹的刪除其實和插入很是類似,只是更加複雜一點,由於刪除能夠從任意節點刪除,而並不是只能從葉子節點刪除。因此就涉及到刪除後保持結構定義的過程。這裏就再也不贅述刪除具體的流程,比較複雜。建議你們去看一下《算法導論》286頁,有詳細的描述。oop
這裏能夠看到 Max. Degree = 3 表示是一個三階B樹,因此他的關鍵字最多隻能有三個。性能
這時候若是咱們再插入1,就會發現,結構並不會恢復成以前的樣子。 動畫
其實從剛剛的插入刪除的演示中就已經能夠看出查詢的過程,搜索一顆B樹和搜索一顆二叉搜索樹相似,不一樣的就在於每一個節點的分支選擇是多叉的,而不必定是二叉。
爲了探究這個問題咱們首先應該瞭解幾個知識
索引就是一種數據結構,須要存儲,而且索引也不僅僅在內存中,須要存儲到磁盤中。
在我以前的博文中提到過,實際上數據庫查詢數據是先查主存,若是不存在,纔去磁盤中查詢,而後帶到主存裏來。這裏在磁盤查詢的過程當中會涉及到磁盤的io,實際上若是不考慮從主存中查詢,最影響數據庫查詢速度的就是磁盤IO,所以儘可能減小磁盤IO就能夠顯著的提高數據的查詢速度。
傳統的磁盤讀取依靠的是機械運動,IO的耗時就分爲尋道時間、旋轉延遲、傳輸時間三個部分。**SSD則不一樣。**爲了減小io的消耗,採用來預讀的機制。當訪問一個地址數據的時候,與其相鄰的數據很快也會被訪問到。每次磁盤IO讀取的數據咱們稱之爲一頁(page)。一頁的大小與操做系統有關,通常爲4k或者8k。這也就意味着讀取一頁內數據的時候,實際上發生了一次磁盤IO。
經過上面幾點,咱們就能夠知道,索引會寫盤,查詢索引的過程就是查詢節點的過程若是不在內存中就會去查找磁盤,產生磁盤IO,那麼索引的查詢速度大部分就取決於每次查詢須要訪問的數據頁。咱們能夠假設一棵 100 萬節點的平衡二叉樹,樹高 20。一次查詢可能須要訪問 20 個數據塊。而若是使用b樹的話就取決於咱們N叉樹的N的大小。固然,這裏B+樹也是同理的。
B+樹其實就是B樹和順序索引訪問方法演化而來的,在這裏就不贅述B樹和B+樹的區別了,你們只要知道B樹的每一個結點都存儲了key和data,B+樹的data存儲在葉子節點上。
B+樹其實就是B樹的變體,和B樹很類似。如圖是一個三階B+樹。
從圖中咱們能夠和清楚的看到,實際上B+樹的插入和刪除的過程和B樹基本一致,惟一區別是,B+樹經過一個雙向鏈表把葉子節點連接起來,在維護樹的時候一樣須要維護這個雙向鏈表,這裏也不仔細去說詳細的插入刪除的算法。詳見《Mysql技術內幕 InnoDB存儲引擎》 P202
查詢過程其實也是接近的,區別只是B+樹的節點沒有存儲data,因此其實是查到鏈表中。
非葉子節點不存儲數據就意味着存放一樣多的key, 樹的層高能進一步被壓縮, 使得檢索的時間更短。而且葉子結點是鏈表形式,能更快的進行順序遍歷。
也就是主鍵索引,葉子節點存儲的是整行的數據,而且數據也是依據主鍵索引進行排序,主鍵索引一張表只能有一個也是由於數據只能按照一個索引進行排序。聚簇索引附帶惟一性約束。
也叫輔助索引,葉子節點並不存放整行數據,而是存儲主鍵的值。要查找到完整數據須要回表。
用來確保表中沒有兩個數據行具備徹底相同的鍵值通常咱們使用它來幫助維護數據完整性。同時須要注意惟一性約束不等於惟一索引。
普通索引,用來輔助查詢,不具有惟一性約束。
索引按照順序遞增(不必定要連續,只要是遞增就行),索引緊湊;隨機插入爲了保證索引的順序行可能會形成索引的數據頁分裂。數據頁的分裂就產生數據空洞。分裂過程不只影響性能還會影響空間使用率,由於本來一個數據頁的數據,分紅了兩個數據頁。 固然有分裂就有合併。當相鄰兩個頁因爲刪除了數據,利用率很低以後,會將數據頁作合併。合併的過程,能夠認爲是分裂過程的逆過程。
這裏引用一張《Mysql 45講》中的圖
非聚簇索引查詢到主鍵,回到聚簇索引搜索的過程,咱們稱爲回表。
覆蓋索引並非一種索引類型,而是從非聚簇索引中就能夠查詢到的結果不用,再去回表。這種操做能夠的好處是,非聚簇索引只存儲索引值,並無整行的數據,故其大小遠小於聚簇索引,能夠減小大量的io操做,因此咱們常說不要用select *。
聯合索引是指對錶上的多個列進行索引,聯合索引也是一棵B+樹,不一樣的是聯合索引的鍵值數量不是1,而是大於等於2。 這裏須要注意的是聯合索引的結構 聯合索引的全部索引列都出如今索引樹上,並依次比較三列的大小進行排序。
做者水平有限,如有錯誤遺漏,請指出。
參考文章
5.MySQL技術內幕 InnoDB存儲引擎 第2版