上一篇文章分析了索引失效的原因之一-索引采样统计,今天我们继续聊一聊索引失效的其他情况和原因,建表语句如下
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `password` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `age` int(4) NOT NULL, `hobbys` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (`id`) USING BTREE, KEY `name` (`username`) USING BTREE, KEY `hobbys` (`hobbys`) USING BTREE ) ENGINE=InnoDB CHARSET=utf8;
表中现在只有一条数据
现在我们 介绍第一种情况,函数转换,注意只有在条件字段上这样操作才会失效
模糊查询索引是生效的,现在我们用函数截取字符串再试试
可以看到,索引已经失效了,那么索引失效的原因究竟是什么呢,我用一张图来解释,我们现在假设表中有7条记录,索引树是这样的
那么你不难看出如果我们将字段截取一部分出来之后根本没有办法使用树搜索,也就是说查询不知道该走哪条路,树搜索的必要条件是索引组织必须有序,显然函数转换已经改变了索引的顺序,没有办法使用树搜索。
第二种情况:隐式类型转换
隐式类型转换你需要明白一点,mysql是会将字符串转为整型,至于证明方式大家可以自行尝试。
这样的语句相当于给username加上了cast函数,索引失效。
第三种情况:字段编码转换
这种情况多出现于连表查询,这里为了简单,我直接用user表,建表时username字段和hobbys均有索引,但是字段编码不同:
可以看到,hobbys字段的索引是生效了,但是username字段的索引失效了,原因是在username字段上发生了编码转换,解决办法就是避免编码转换。
其他情况:
优化器有的时候即便不出现上述情况也会全表扫描,要说原因的话,大概是因为偷懒吧,比如说如下语句:
显然这里没有出现类型转换,你可能会说,索引顺序不对了,但是优化器是完全可以将id+1=124改成id=124-1;这样的话显然是可以的
另外我总是在网上或者一些程序猿那里听到一种说法,or会使索引失效,那么我们试一试
可以看到,同一个索引使用or并不会出现问题,不同的索引使用or就会失效,这个问题的原因我就不做赘述,如果有问题的话欢迎评论区提问。
文章编写不易,转载请声明出处,谢谢。



