likes
comments
collection
share

记录一次工作中遇到的索引失效的经历

作者站长头像
站长
· 阅读数 22

几个月前经理让给报表新增几个展示字段,需要将原有的sql关联新的表,改完之后发现查询速度奇慢无比,经过排查之后发现改加的索引都加上了,但是MySQL就是在联表的时候不走联表字段的索引,一开始我以为是因为MySQL底层的优化机制导致不选择走这条索引,所以结合之前学到的相关知识在对应的位置加上了强制走索引的关键字force index(),但是结果是依旧不走这个索引,得益于当时正好在学习MySQL底层的一些知识,发现是因为联表的两个字段排序规则不一致,从而导致索引失效。

简单模拟一下

首选关注两个表的结构:

员工表: 记录一次工作中遇到的索引失效的经历 岗位表: 记录一次工作中遇到的索引失效的经历

我们将员工表左关联岗位表,用job_id字段进行关联,因为job_id作为岗位表的主键,一般来说是会走索引的,我们看到的explain执行结果也是如此。

记录一次工作中遇到的索引失效的经历

但是当我们将岗位表的排序规则调整一下,调整为utf8mb4_general_ci 记录一次工作中遇到的索引失效的经历

然后再来执行一下 记录一次工作中遇到的索引失效的经历 会发现结果是不走索引的,所以可以发现排序规则确实会影响是否走索引。

但是是不是排序规则不一致就一定不会走索引呢,其实也未必,经过几次尝试,发现如果把上面两个表的排序规则互换一下,再执行就会发现结果又可以走索引了,是不是很神奇。

记录一次工作中遇到的索引失效的经历

记录一次工作中遇到的索引失效的经历

结果: 记录一次工作中遇到的索引失效的经历

我个人觉得可能是因为这两个排序规则是有一个类似兼容的关系的,utf8mb4_bin可以兼容utf8mb4_general_ci,但是utf8mb4_general_ci却不兼容utf8mb4_bin,所以使用排序类型为utf8mb4_general_ci的字段的值去utf8mb4_bin排序规则的表里查询,是可以走索引的,可以理解为不需要将utf8mb4_bin转为utf8mb4_general_ci,这里的转换可以理解为函数处理,但是反过来就需要对排序规则排序规则做函数处理进行转换,那么相当于给索引字段包上了一层函数,再根据这个字段查询的话索引自然会失效。