**1\. 什么是索引?**
索引是一種數據結構,可以幫助我們快速的進行數據的查找.
*****
**2\. 索引是個什么樣的數據結構呢?**
索引的數據結構和具體存儲引擎的實現有關, 在MySQL中使用較多的索引有Hash索引,B+樹索引等,而我們經常使用的InnoDB存儲引擎的默認索引實現為:B+樹索引.
*****
**3\. Hash索引和B+樹所有有什么區別或者說優劣呢?**
首先要知道Hash索引和B+樹索引的底層實現原理:
*****
hash索引底層就是hash表,進行查找時,調用一次hash函數就可以獲取到相應的鍵值,之后進行回表查詢獲得實際數據.B+樹底層實現是多路平衡查找樹.對于每一次的查詢都是從根節點出發,查找到葉子節點方可以獲得所查鍵值,然后根據查詢判斷是否需要回表查詢數據.
那么可以看出他們有以下的不同:
* hash索引進行等值查詢更快(一般情況下),但是卻無法進行范圍查詢.
因為在hash索引中經過hash函數建立索引之后,索引的順序與原順序無法保持一致,不能支持范圍查詢.而B+樹的的所有節點皆遵循(左節點小于父節點,右節點大于父節點,多叉樹也類似),天然支持范圍.
* hash索引不支持使用索引進行排序,原理同上.
* hash索引不支持模糊查詢以及多列索引的最左前綴匹配.原理也是因為hash函數的不可預測.AAAA和AAAAB的索引沒有相關性.
* hash索引任何時候都避免不了回表查詢數據,而B+樹在符合某些條件(聯合索引索引,覆蓋索引等)的時候可以只通過索引完成查詢.
* hash索引雖然在等值查詢上較快,但是不穩定.性能不可預測,當某個鍵值存在大量重復的時候,發生hash碰撞,此時效率可能極差.而B+樹的查詢效率比較穩定,對于所有的查詢都是從根節點到葉子節點,且樹的高度較低.
因此,在大多數情況下,直接選擇B+樹索引可以獲得穩定且較好的查詢速度.而不需要使用hash索引.
*****
**4\. 上面提到了B+樹在滿足聚簇索引和覆蓋索引的時候不需要回表查詢數據,什么是聚簇索引?**
**聚簇索引:**將數據存儲與索引放到了一塊,索引結構的葉子節點保存了行數據.
**非聚簇索引:**將數據與索引分開存儲,索引結構的葉子節點指向了數據對應的位置
在InnoDB中,只有主鍵索引是聚簇索引,如果沒有主鍵,則挑選一個唯一鍵建立聚簇索引.如果沒有唯一鍵,則隱式的生成一個鍵來建立聚簇索引.
在聚簇索引之上創建的索引稱之為輔助索引,非聚簇索引都是輔助索引,像復合索引、前綴索引、唯一索引。**輔助索引葉子節點存儲的不再是行的物理位置,而是主鍵值,輔助索引訪問數據總是需要二次查找**
當查詢使用聚簇索引時,在對應的葉子節點,可以獲取到整行數據,因此不用再次進行回表查詢.
*****
**5\. 非聚簇索引一定會回表查詢嗎?**
不一定,這涉及到查詢語句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再進行回表查詢.
舉個簡單的例子,假設我們在員工表的年齡上建立了索引,那么當進行select age from employee where age < 20的查詢時,在索引的葉子節點上,已經包含了age信息,不會再次進行回表查詢.
*****
**6\. 在建立索引的時候,都有哪些需要考慮的因素呢?**
建立索引的時候一般要考慮到字段的使用頻率,經常作為條件進行查詢的字段比較適合.如果需要建立聯合索引(用多個字段建立一個索引)的話,還需要考慮聯合索引中的順序(和查詢條件有關).此外也要考慮其他方面,比如防止過多的索引對表造成太大的壓力(explain時會有優化分析).這些都和實際的表結構以及查詢方式有關.
*****
**7\. 聯合索引是什么?為什么需要注意聯合索引中的順序?**
MySQL可以使用多個字段同時建立一個索引,叫做聯合索引.在聯合索引中,如果想要命中索引,需要按照建立索引時的字段順序挨個使用,否則無法命中索引.
具體原因為:
MySQL使用索引時需要索引有序,假設現在建立了"name,age,school"的聯合索引,那么索引的排序為: 先按照name排序,如果name相同,則按照age排序,如果age的值也相等,則按照school進行排序.
當進行查詢時,此時索引僅僅按照name嚴格有序,因此必須首先使用name字段進行等值查詢,之后對于匹配到的列而言,其按照age字段嚴格有序,此時可以使用age字段用做索引查找,,,以此類推.因此在建立聯合索引的時候應該注意索引列的順序,一般情況下,將查詢需求頻繁或者字段選擇性高的列放在前面.此外可以根據特例的查詢或者表結構進行單獨的調整.
*****
**8\. 創建的索引有沒有被使用到?或者說怎么才可以知道這條語句運行很慢的原因?**
MySQL提供了**explain**命令來查看語句的執行計劃,MySQL在執行某個語句之前,會將該語句過一遍查詢優化器,之后會拿到對語句的分析,也就是執行計劃,其中包含了許多信息. 可以通過其中和索引有關的信息來分析是否命中了索引,例如possilbe\_key(可能會選擇的索引),key(實際選擇的索引),key\_len(索引長度)等字段,分別說明了此語句可能會使用的索引,實際使用的索引以及使用的索引長度.
*****
**9\. 那么在哪些情況下會發生針對該列創建了索引但是在查詢的時候并沒有使用呢?**
* 使用不等于查詢,
* 列參與了數學運算或者函數
* 在字符串like時左邊是通配符.類似于'%aaa'.
* 當mysql分析全表掃描比使用索引快的時候不使用索引.