TDSQL MySQL的索引分類問題一直讓人頭疼,幾乎全部的資料都會給你列一個長長的清單,給你介紹什麼主鍵索引、單值索引,覆蓋索引,自適應哈希索引,全文索引,聚簇索引,非聚簇索引等……給人的感受就是雲裏霧裏,好像MySQL索引的實現方式有不少種,可是都沒有一個清晰的分類。因此本人嘗試總結了一下如何給MySQL的索引類型分類,便於你們記憶,因爲MySQL中支持多種存儲引擎,在不一樣的存儲引擎中實現略微有所差距,下文中若是沒有特殊聲明,默認指的都是InnoDB存儲引擎。sql
索引從不一樣維度劃分能夠有不少種名稱,可是須要明確一個問題——索引的本質是一種數據結構,其餘索引的劃分則是針對實際應用而言。數據結構
1、根據底層數據結構劃分工具
索引是提升查詢效率的數據結構,而可以提升查詢效率的數據結構有不少,如二叉搜索樹,紅黑樹,跳錶,哈希表(散列表)等,而MySQL中用到了B+Tree和散列表(Hash表)做爲索引的底層數據結構(其實也用到了跳錶實現全文索引,但這不是重要考點,因此能夠忽略)。性能
- hash索引
MySQL並無顯式支持Hash索引,而是做爲內部的一種優化。具體在Innodb存儲引擎裏,會監控對錶上二級索引的查找,若是發現某二級索引被頻繁訪問,二級索引成爲熱數據,就爲之創建hash索引。所以,在MySQL的Innodb裏,對於熱點的數據會自動生成Hash索引。這種hash索引,根據其使用的場景特色,也叫自適應Hash索引。優化
- B+樹索引
這個是MySQL索引的基本實現方式。除了全文索引、hash索引,Innodb、MyISAM的索引都是經過B+樹實現的。url
2、根據索引字段個數劃分.net
爲了能應對不一樣的數據檢索需求,索引既能夠僅包含一個字段,也能夠同時包含多個字段。單個字段組成的索引能夠稱爲單值索引,不然稱之爲複合索引,也稱爲組合索引或多值索引。指針
這個很好理解,假如咱們有一張表,有三個屬性,分別是 id,age 和 name 。假如在id上創建索引,那這就是單值索引;若是在 name 和 age 上創建索引,那這就是複合索引。blog
複合索引的索引的數據順序跟字段的順序相關,包含多個值的索引中,若是當前面字段的值重複時,將會按照其後面的值進行排序。排序
使用覆蓋索引的前提是字段長度比較短,對於值長度較長的字段則不適合使用覆蓋索引,緣由有不少,好比索引通常存儲在內存中,若是佔用空間較大,則可能會從磁盤中加載,影響性能。
3、根據是不是在主鍵上創建的索引進行劃分
- 主鍵索引
MySQL中是根據主鍵來組織數據的,因此每張表都必須有主鍵索引,主鍵索引只能有一個,不能爲null同時必須保證惟一性。建表時若是沒有指定主鍵索引,則會自動生成一個隱藏的字段做爲主鍵索引。
- 輔助索引
若是不是主鍵索引,則就能夠稱之爲非主鍵索引,又能夠稱之爲輔助索引或者二級索引。主鍵索引的葉子節點存儲了完整的數據行,而非主鍵索引的葉子節點存儲的則是主鍵索引值,經過非主鍵索引查詢數據時,會先查找到主鍵索引,而後再到主鍵索引上去查找對應的數據。
在這裏假設咱們有張表user,具備三列:ID,age,name,create_time,id是主鍵,(age,create_time,,name)創建輔助索引。執行以下sql語句:
select name from user where age>2 order by create_time desc。
正常的話,查詢分兩步:
1.按照輔助索引,查找到記錄的主鍵,
2.按照主鍵主鍵索引裏查找記錄,返回name。
但實際上,咱們能夠看到,輔助索引節點是按照age,create_time,name創建的,索引信息裏徹底包含咱們所要的信息,若是能從輔助索引裏返回name信息,則第二步是徹底沒有必要的,能夠極大提高查詢速度。
按照這種思想Innodb裏針對使用輔助索引的查詢場景作了優化,叫覆蓋索引(在這裏小聲吐槽一下,不知道業界起這種名詞幹嗎,太容易引發歧義了,叫個索引覆蓋查詢不是更好嗎)。
4、根據數據與索引的存儲關聯性劃分
根據數據與索引的存儲關聯性,能夠分爲聚簇索引和非聚簇索引(也叫彙集索引和非彙集索引)。聚簇索引也叫簇類索引,是一種對磁盤上實際數據從新組織以按指定的一個或多個列的值排序。整個簡潔的說法,這倆的區別就是索引的存儲順序和數據的存儲順序是不是關係的,有關就是聚簇索引,無關就是非聚簇索引。具體實現方式根據索引的數據結構不一樣會有所不一樣。下面以B+樹實現的索引爲例,舉例來講明聚簇索引和非聚簇索引。
- 聚簇索引
Innodb的主鍵索引,非葉子節點存儲的是索引指針,葉子節點存儲的是既有索引也有數據,是典型的聚簇索引(這裏能夠發現,索引和數據的存儲順序是強相關的。所以是典型的聚簇索引),如圖:
- 非聚簇索引
MyISAM中索引和數據文件分開存儲,B+Tree的葉子節點存儲的是數據存放的地址,而不是具體的數據,是典型的非聚簇索引;換言之,數據能夠在磁盤上隨便找地方存,索引也能夠在磁盤上隨便找地方存,只要葉子節點記錄對了數據存放地址就行。所以,索引存儲順序和數據存儲關係毫無關聯,是典型的非聚簇索引,另外Inndob裏的輔助索引也是非聚簇索引。
5、其餘分類
- 惟一索引
顧名思義,不容許具備索引值相同的行,從而禁止重複的索引或鍵值。系統在建立該索引時檢查是否有重複的鍵值,並在每次使用 INSERT 或 UPDATE 語句添加數據時進行檢查, 若是有重複的值,則會操做失敗,拋出異常。
須要注意的是,主鍵索引必定是惟一索引,而惟一索引不必定是主鍵索引。惟一索引能夠理解爲僅僅是將索引設置一個惟一性的屬性。
- 全文索引
在MySQL 5.6版本之前,只有MyISAM存儲引擎支持全文引擎。在5.6版本中,InnoDB加入了對全文索引的支持,可是不支持中文全文索引.在5.7.6版本,MySQL內置了ngram全文解析器,用來支持亞洲語種的分詞。主要用來利用關鍵詞查詢文本,不是MySQL的主要面向場景,使用較少,這裏就不展開討論了。
6、總結
最後總結一張腦圖方便記憶:
本文由博客羣發一文多發等運營工具平臺 OpenWrite 發佈