版本MySQL5.7.34
有一個student表,欄位如下
-
id
-
name
-
age
-
position
-
sex
建立聯合索引(name, age, position)
問以下的SQL哪些會使用這個索引?
1、explain select * from student where name > 'AAA'
2、explain select * from student where age = 25
3、explain select name, age, sex from student where name like '%A' and age = 25
4、explain select name, age from student where name like '%A' and age = 25
5、explain select name from student where name like '%A'
解釋:
第一句和第二句很基礎,第一句可以,第二句不行,因為違背最左匹配原則
第三句也不行,因為是左模糊匹配,並且索引沒有覆蓋要查詢的欄位
那第四句呢?
第四句很明顯是左模糊匹配,一般情況下我們會認為無法使用索引,但是實際上是可以的,原因如下
-
首先這個索引覆蓋了全部查詢欄位,在MySQL5.7以及之後的版本,最佳化器得到了較大的提升,會評估“全表掃描”以及“全索引掃描”的代價差距,一般情況下,如果索引能覆蓋查詢欄位,會使用覆蓋索引進行全索引掃描。
-
為什麼全索引掃描要效能更好?因為覆蓋索引包含的欄位是少於聚簇索引的,MySQL中一頁的大小是固定的,覆蓋索引載入相同數量的頁可以載入更多的資料,從而減少IO次數,而我們知道MySQL的主要瓶頸其實就是磁碟IO。
-
其次age使用了等值查詢,所以可以在全索引掃描之後,查詢到符合的記錄,再使用age列進行索引使用,提高過濾age時的效能。
第五句SQL同理,全掃描覆蓋索引代價是更低的,所以會使用覆蓋索引。
如果例如第三句SQL,有一個欄位在索引外部,無法使用覆蓋索引,就算使用了,也還需要回表查詢其它欄位,MySQL就會直接全表掃描。