MySQL索引失效問題總結


先來思考一個小問題。

問題:當查詢條件為2個及2個以上時,是創建多個單列索引還是創建一個聯合索引好呢?它們之間的區別是什么?哪個效率高呢?

先來建立一些單列索引進行測試:

這里建立了一張表,里面建立了三個單列索引userId,mobile,billMonth。

然后進行多列查詢。

explain select * from `t_mobilesms_11` where userid = '1' and mobile = '13504679876' and billMonth = '1998-03'

我們發現查詢時只用到了userid這一個單列索引,這是為什么呢?因為這取決於MySQL優化器的優化策略。

當多條件聯合查詢時,優化器會評估哪個條件的索引效率高,它會選擇最佳的索引去使用。也就是說,此處三個索引列都可能被用到,只不過優化器判斷只需要使用userid這一個索引就能完成本次查詢,故最終explain展示的key為userid。

4.1 總結

多個單列索引在多條件查詢時優化器會選擇最優索引策略,可能只用一個索引,也可能將多個索引都用上。

但是多個單列索引底層會建立多個B+索引樹,比較占用空間,也會浪費搜索效率
所以多條件聯合查詢時最好建聯合索引。

那聯合索引就可以三個條件都用到了嗎?會出現索引失效的問題嗎?

4.2 聯合索引失效問題

一張圖搞懂MySQL的索引失效

1)違反最左匹配原則

最左匹配原則:最左優先,以最左邊的為起點任何連續的索引都能匹配上,如不連續,則匹配不上。

如:建立索引為(a,b)的聯合索引,那么只查 where b = 2 則不生效。換句話說:如果建立的索引是(a,b,c),也只有(a),(a,b),(a,b,c)三種查詢可以生效。

這里跳過了最左的name字段進行查詢,發現索引失效了。

遇到范圍查詢(>、<、between、like)就會停止匹配。

比如:a= 1 and b = 2 and c>3 and d =4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,因為c字段是一個范圍查詢,它之后的字段會停止匹配。

2)在索引列上做任何操作

如計算、函數、(手動或自動)類型轉換等操作,會導致索引失效而進行全表掃描。

explain select * from user where left(name,3) = 'zhangsan' and age =20

這里對name字段進行了left函數操作,導致索引失效。

3)使用不等於(!= 、<>)

explain select * from user where age != 20;
explain select * from user where age <> 20;

4)like中以通配符開頭('%abc')

索引失效

explain select * from user where name like ‘%zhangsan’;

索引生效

explain select * from user where name like ‘zhangsan%’;

5)字符串不加單引號索引失效

explain select * from user where name = 2000;

6)or連接索引失效

explain select * from user where name = ‘2000’ or age = 20 or pos =‘cxy’;

7)order by

正常(索引參與了排序),沒有違反最左匹配原則。

explain select * from user where name = 'zhangsan' and age = 20 order by age,pos;

違反最左前綴法則,導致額外的文件排序(會降低性能)。

explain select name,age from user where name = 'zhangsan' order by pos;

8)group by

正常(索引參與了排序)。

explain select name,age from user where name = 'zhangsan' group by age;

違反最左前綴法則,導致產生臨時表(會降低性能)。

explain select name,age from user where name = 'zhangsan' group by pos,age;


免責聲明!

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



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