圖解MySQL索引(上)—MySQL有中「8種」索引?

關於MySQL索引相關的內容,一直是一個讓人頭疼的問題,尤爲是對於初學者來講。筆者曾在很長一段時間內深陷其中,沒法分清「覆蓋索引,輔助索引,惟一索引,Hash索引,B-Tree索引……」究竟是些什麼東西,致使在面試過程當中進入比較尷尬的局面。html

不少人可能會抱怨」面試造火箭,工做擰螺絲,不少知識都是爲了面試學的,工做中根本用不到!「。慶幸的是,MySQL中索引不只是面試必考知識,仍是工做中用到最爲頻繁的必備技能,在筆者看來,索引是MySQL中性價比最高的一部份內容面試

因爲MySQL中支持多種存儲引擎,在不一樣的存儲引擎中實現略微有所差距,索引下文中若是沒有特殊聲明,默認指的都是InnoDB存儲引擎,下文中索引基於這張user表來進行演示。數據庫

id name age
001 Lily 18
002 Tom 20
003 Jack 19
004 John 28
005 Alice 24
006 Lucy 21
007 Rose 18
008 Steven 16

1、索引的底層數據結構

首先,索引是高效獲取數據的數據結構。就像書中的目錄同樣,咱們能夠經過它快速定位到數據所在的位置,從而提升數據查詢的效率。編程

在MySQL中有許多關於索引的名詞和概念,對於初學者來講很容易被迷惑。爲了方便理解,我創建了一張表,從具體的案例中嘗試說清楚這些概念究竟是什麼。數據結構

Hash索引app

正如上文中說到,索引是提升查詢效率的數據結構,而可以提升查詢效率的數據結構有不少,如二叉搜索樹,紅黑樹,跳錶,哈希表(散列表)等,而MySQL中用到了B+Tree和散列表(Hash表)做爲索引的底層數據結構。編程語言

須要注意的是,MySQL並無顯式支持Hash索引,而是做爲內部的一種優化,對於熱點的數據會自動生成Hash索引,也叫自適應Hash索引性能

Hash索引在等值查詢中,能夠O(1)時間複雜度定位到數據,效率很是高,可是不支持範圍查詢。在許多編程語言以及數據庫中都會用到這個數據結構,如Redis支持的Hash數據結構。具體結構以下:優化

B+Tree索引spa

提到B+Tree首先不的不提B-Tree,B-Tree(多路搜索樹,並非二叉的)是一種常見的數據結構。使用B-tree結構能夠顯著減小定位記錄時所經歷的中間過程,從而加快存取速度。

B+ 樹是基於B-Tree升級後的一種樹數據結構,一般用於數據庫和操做系統的文件系統中。B+ 樹的特色是可以保持數據穩定有序,其插入與修改擁有較穩定的對數時間複雜度。B+ 樹元素自底向上插入,這與二叉樹剛好相反。

MySQL索引的實現也是基於這種高效的數據結構。具體數據結構以下:

筆者首先要聲明一下,不要將B樹,B-Tree以及B+Tree弄混淆。首先,B-Tree就是B樹,中間的「-」是一箇中劃線,而不是減號,並不存在"B減樹"這種數據結構。其次,就是B+Tree和B-Tree實現索引時有兩個區別,具體可見下圖

①B+Tree只在葉子節點存儲數據,而B-Tree的數據存儲在各個節點中

②B+Tree的葉子節點間經過指針連接,能夠經過遍歷葉子節點便可獲取全部數據。

B+Tree是一種神奇的數據結構,若是用語言來說可能會優勢費勁,感興趣的同窗能夠點擊這裏進行數據結構可視化,操做一番後想必會有所收穫,下圖是筆者演示B+Tree的數據插入方式(自下而上)。

二,數據組織方式

根據數據的組織方式,能夠分爲聚簇索引和非聚簇索引(也叫彙集索引和非彙集索引)。若是是索引組織數據,就稱之爲聚簇索引,不然稱之爲非聚簇索引,簡單來講索引和數據是否存儲在一塊兒

須要注意的是,這種索引劃分方式一般用來體現不一樣存儲引擎的組織數據方式的差別(一般指的是InnoDB和MyISAM存儲引擎)。而InnoDB中的輔助索引並不能稱之爲非聚簇索引,關於輔助索引的內容,下文會進行詳細介紹。InnoDB中是經過索引來組織數據,爲聚簇索引。

而MyISAM中索引和數據文件分開存儲,爲非聚簇索引。B+Tree的葉子節點存儲的是數據存放的地址,而不是具體的數據 。

三,索引字段個數

爲了能應對不一樣的數據檢索需求,索引便可以僅包含一個字段,也能夠同時包含多個字段。單個字段組成的索引能夠稱爲單值索引,不然稱之爲複合索引(或者稱爲組合索引或多值索引)。上文中演示的都是單值索引,因此接下來展現一下複合索引做爲對比。

複合索引的索引的數據順序跟字段的順序相關,包含多個值的索引中,若是當前面字段的值重複時,將會按照其後面的值進行排序。

四, 是否存儲完整數據行

MySQL中是根據主鍵來組織數據,因此每張表都必須有主鍵索引,主鍵索引只能有一個,不能爲null同時必須保證惟一性。建表時若是沒有指定主鍵索引,則會自動生成一個隱藏的字段做爲主鍵索引。

若是不是主鍵索引,則就能夠稱之爲非主鍵索引,又能夠稱之爲輔助索引,二級索引。主鍵索引的葉子節點存儲了完整的數據行,而非主鍵索引的葉子節點存儲的則是主鍵索引值,經過非主鍵索引查詢數據時,會先查找到主鍵索引,而後再到主鍵索引上去查找對應的數據,這個過程叫作回表(下文中會再次提到)。

五,其餘分類

惟一索引

惟一索引,不容許具備索引值相同的行,從而禁止重複的索引或鍵值。系統在建立該索引時檢查是否有重複的鍵值,並在每次使用 INSERT 或 UPDATE 語句添加數據時進行檢查, 若是有重複的值,則會操做失敗,拋出異常。

須要注意的時,主鍵索引必定時惟一索引,而惟一索引不必定時主鍵索引。惟一索引能夠理解爲僅僅是將索引設置一個惟一性的屬性

覆蓋索引

上文提到了一個回表的概念,既若是經過非主鍵索引查詢數據時,會先查詢到主鍵索引的值,而後再去主鍵索引中查詢具體的數據,整個查詢流程須要掃描兩次索引,顯然回表是一個耗時的操做。

爲了減小回表次數,再設計索引時咱們能夠讓索引中包含要查詢的結果,在輔助索引中檢索到數據後直接返回,而不須要進行回表操做。

可是須要注意的是,使用覆蓋索引的前提是字段長度比較短,對於值長度較長的字段則不適合使用覆蓋索引,緣由有不少,好比索引通常存儲在內存中,若是佔用空間較大,則可能會從磁盤中加載,影響性能。固然還有其餘緣由,具體狀況將會在下一篇文章中介紹。

六,總結

本文從不一樣維度介紹了MySQL中的索引,索引從不一樣維度劃分能夠有不少種名稱,可是須要明確一個問題就是,索引的本質是一種數據結構,其餘索引的劃分則是針對實際應用而言。具體分類以下圖所示:

目的是讓你們對於索引有個初步且清晰的認識,解決What的問題。後續將會針對Why以及How,進行深刻探討,固然,首先應當能區分本章文章中講述的概念性問題。

7、Q&A

1. 爲何MySQL索引使用B+Tree實現,而不是搜索二叉樹,紅黑樹或者跳錶?

這是一個綜合性問題,遠不止看起來那麼簡單,小夥伴們能夠把答案寫在留言區咱們一塊兒探討,一樣筆者將會在下一篇文章中重點介紹爲何,以及如何正確使用索引。

相關文章
相關標籤/搜索