反直覺SQL舉例說明

枫叶藏在眼眸發表於2024-09-01

版本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就會直接全表掃描。

相關文章