阿里面試題: (a,b,c)組合索引, 查詢語句select...from...where a=.. and c=..走索引嗎?


面試官:(a,b,c)組合索引,查詢語句select...from...where a=.. and c=..走索引嗎應聘者:

  • 最佳左前綴法,如果索引了多列,要遵守最左前綴法則,否則索引失效

  • 按最左前綴原則,a能走索引,c走不了,只能用到a部分索引

接下來,我們具體來分析一下

 

1、組合索引在樹中是如何排序的

在MySQL中建立聯合索引時會遵守最左前綴匹配原則,即最左優先。要想理解聯合索引的最左匹配原則,先來理解下索引的底層原理。索引的底層是一顆B+樹,那么聯合索引的底層也就是一顆B+樹,只不過聯合索引的B+樹節點中存儲的是鍵值。由於構建一棵B+樹只能根據一個值來確定索引關系,所以數據庫依賴聯合索引最左的字段來構建。

舉個栗子:創建一個(a,b)的聯合索引,那么它的索引樹就是下圖的樣子。

可以看到a的值是有順序的:1,1,2,2,3,3,而b的值是沒有順序的1,2,1,4,1,2。但是我們又可發現a在等值的情況下,b值又是按順序排列的,但是這種順序是相對的。這是因為MySQL創建聯合索引的規則是首先會對聯合索引的最左邊第一個字段排序,在第一個字段的排序基礎上,然后在對第二個字段進行排序,所以b=2這種查詢條件沒有辦法利用索引。

 

2、真實案例分析

我們來建立一張用戶表,在user_name,age,user_sex上建立組合索引

按照最左原則,我們按以下方式查詢數據:

通過觀察上面的結果圖可知,where后面的查詢條件,不論是使用(user_name)、(user_name,age) 還是 (user_name,age,user_sex),在查詢時都使用到了聯合索引。

那我們打亂查詢的順序,又會是什么效果呢?

由上圖可知,即便我們打亂了查詢順序,仍然可以使用到索引,這是因為MySQL中有查詢優化器explain,所以sql語句中字段的順序不需要和聯合索引定義的字段順序相同,查詢優化器會判斷糾正這條SQL語句以什么樣的順序執行效率高,最后才能生成真正的執行計划,所以不論以何種順序都可使用到聯合索引。

接下來我們再來看問題的場景:

由上圖可知,我們也用到了索引,但是只用了部分索引,也就是user_name部分的索引,還可以從另外一個字段ref看到,使用的常量const只有一個。聯合索引樹是按照user_name字段創建的,但user_sex相對於user_name來說是無序的,只有user_name是有序的,所以只能使用聯合索引中的user_name索引。

接下來我們再來看因為不滿足最左原則導致的索引失效場景:

由上圖可知,因為不滿足最左原則,本來要以user_name排序開始,現在user_name斷層了,沒辦法使用后面的索引了,故變成全表掃描了。

那我們有什么辦法可以解決這種失效問題呢?

由上圖可知,我們查詢的不是全表字段,而是索引字段,通過觀察發現上面key字段在搜索中也使用了idx_user_nameAgeSex索引,可能許多同學就會疑惑它並沒有遵守最左匹配原則,按道理會索引失效,為什么也使用到了聯合索引?因為沒有從age始匹配,且age單獨來說是無序的,所以它確實不遵循最左匹配原則,然而從type字段可知,它雖然使用了聯合索引,但是它是對整個索引樹進行了掃描,正好匹配到該索引,與最左匹配原則無關,一般只要是某聯合索引的一部分,但又不遵循最左匹配原則時,都可能會采用index類型的方式掃描,但它的效率遠不如最做匹配原則的查詢效率高,index類型類型的掃描方式是從索引第一個字段一個一個的查找,直到找到符合的某個索引,與all不同的是,index是對所有索引樹進行掃描,而all是對整個磁盤的數據進行全表掃描。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM