先申明,我已经把不同表频繁用的字段做了索引了,如下:
`user_group`.`id` 主索引
`user_groupmap`.`user_group_id` 普通索引
`user_groupmap`.`user_id ` 普通索引
今天在用 Explain(执行计划)测试Mysql查询语句性能的时候发现,每当我执行如下SQL的时候:
EXPLAIN SELECT * FROM `user_group` INNER JOIN `user_groupmap` on `user_groupmap`.`user_group_id` = `user_group`.`id` WHERE `user_id` = 71
返回来的结果都有一个:
Extra=Using index condition ,具体如下图:
原因:
Mysql Explain 为什么会出现Extra值为Using index condition?
想知道原因前,大家需要先了解一下:Using index condition代表的是什么意思?
using index condition:搜索条件中虽然出现了索引列,但是有部分条件无法使用索引,会根据能用索引的条件先搜索一遍再匹配无法使用索引的条件。
具体可以参考:MySQL Explain(执行计划)详解
解决方法
我们从上面已经知道了 Extra = Using index condition 是什么意思了。以我这里为例子,我只需要去排查出具体的原因就可以了。
问:我这为什么会出现“搜索条件中虽然出现了索引列,但是有部分条件却无法使用索引”?
答:经过我仔细看上图,我发现了一个问题:为什么 key_len 一个长度为8,一个长度为1?依次类推,可以看到 PRIMARY,表是 user_group。
从而得到这样一个结果:user_group这个表的 PRIMARY 是 id 字段,毕竟PRIMARY只有一个。
当我去 user_group 查看这个表结构的时候,却发现:它的 id 类型居然是 tinyint。
TINYINT[(M)] [UNSIGNED] [ZEROFILL] M默认为4
很小的整数。带符号的范围是-128到127。无符号的范围是0到255。
总算知道了具体的原因了,如下:
字段类型不一样,会造成 key_len 长度不一样,索引的结果也不能保证一致性,从而造成结果一部份有索引,一部份没有索引,所以才提示了 Extra = Using index condition 。
知道了具体的原因,解决起来就简单了,最终解决方法如下:
我只需要把类型:tinyint 改为 bigint 就可以了。你设置为 int 也是可以的,这个根据自己来。我这主要是因为我个人习惯比较喜欢把 PRIMARY 字段的类型都设置为 bigint 类型。
总结:
由于每个人遇到的情况是不一样的,或许你的具体原因跟我的不一样,但是,我的这个思路大家可以去参考一下,只要你懂了 Using index condition 是什么意思?相信你排查起来就容易多了。