Mysql索引失效原理
Mysql索引的本质是有序数据结构,只要查询条件破坏了索引的有序性,索引就会失效,mysql会被迫走全表扫描。
场景1:like模糊查询,%开头必失效
select * from user where name like '%李%' AND age > 20 为啥索引会失效
核心原因:索引是按'李XX','李YY'这样的有序结构存储的。而'%李%'是“包含李”,mysql不知道从哪里开始查询,无法利用索引的有序性,只能全表扫描。
补充:如果是'like '李%''(%在后面)索引不会失效,因为能确定开头是‘李’,能利用索引的有序性快速定位。
场景2:联合索引,不满足“最左前缀原则”必失效。建了联合索引(name,age),不知道为啥(where age>20)会失效。
举个例子,联合索引,就是一本按照(姓名+年龄)排序的电话簿,你想找到‘年龄>20’的人,没法直接定位,因为电话簿不是按年龄排序的,只能从头到尾翻(全表扫描)
关键规则:联合索引必须从左边的字段开始使用,比如 where name='李白' and age>20 会走索引。
where name like '%李%' and age>20 索引都会失效
场景3:索引字段用函数/运算,直接失效
错误写法:select * from user where substring(name,1,1) = '李'(截取姓名首字查询)
原因:Mysql会先对每个name字段做substring运算,再和‘李’比较--运算后的结构是无序的,破坏了索引的有序性,索引直接失效。
正确写法:避免对索引字段做运算 改成 where name like '李%'
场景4:隐式类型转换,索引失效。比如索引字段phone是varchar类型(存手机号),查询语句写 where phone = 13800,用数字匹配字符串,Mysql会自动做类型转换,把phone存起来,相当于对索引字段做了运算,索引直接失效。
正确写法:where phone = '13800'
场景5:or连接查询,有一个字段无索引则全失效
错误写法:select * from user where name='李白' or address = '北京',如果name有索引,address无索引,mysql无法确定如何用索引,会放弃所有索引,直接走全表扫描。要么给address建索引,要么拆分查询。

浙公网安备 33010602011771号