美文网首页MySQL索引MySQL(总)
where条件中出现了(不等于/多重范围)就一定不走索引了吗

where条件中出现了(不等于/多重范围)就一定不走索引了吗

作者: 飞翔的Tallgeese | 来源:发表于2019-02-14 15:02 被阅读2次

    今天朋友抛了一个群里的讨论给我,如下图

    这题我选择了A,B,因为我认为A和B都不满足最左;最后朋友实际建表的测试结果如下(也就是说答案应该是A,B,D)

    按理说不等于不走索引应该是SQL优化的常识了,为什么我在选择的时候排除了D呢?因为2个月前我遇到了这样一个语句

    SELECT MAX(id)

    FROM a

    WHERE user_id != '18'

    AND '2019-02-13 00:00:00' >= create_time

    GROUP BY user_id;

    因为这个语句的关系,我一度认为在5.7.25版本里不等于也已经开始智能的走索引了;经过这个选择题,决定仔细探索一下MySQL的不等于


    对原语句进行不同的改写

    备注:

    ①索引idx_uid_ct为user_id和create_time的联合索引idx_uid_ct(user_id,create_time)

    ②后面为了测试,特意删除了idx_ct(create_time)

    ③id为表的主键列

    eg1.去除group by的影响,type为range,覆盖索引

    eg2.去除max函数,type为range,覆盖索引

    eg3.查询项改为create_time、user_id、id中的任意1到3个,type为range,覆盖索引

    eg4.查询项改为*或者是索引列(user_id,create_time,id)之外的任意值,索引前导列存在不等于,不走索引

    eg5.查询项改为*或者是索引列(user_id,create_time,id)之外的任意值,索引的非前导列存在不等于,走索引,extra为ICP

    eg6.查询项改为create_time或者user_id,where条件改为只有非前导列create_time,不满足idx_uid_ct最左匹配规则,type为index,覆盖索引

    eg7.查询项改为索引列(user_id,create_time,id)之外的任意值,where条件将user_id的不等于改为等于,create_time条件不变,type为range,Extra为ICP

    eg8.查询项改为索引列(user_id,create_time,id)之外的任意值,where条件将user_id的不等于改为大于或者小于,create_time条件不变,是否走索引需要优化器进行判断

    eg9.查询项改为索引列(user_id,create_time,id)之中的任意1-3个值,where条件将user_id的不等于改为大于或者小于,create_time条件不变,type为range,覆盖索引


    结论

    ①对比上面的9个eg可以看出,当查询列位于主键或者索引列范围内的时候(或者像原语句那样是主键/索引列的分组函数),整个语句会直接走覆盖索引,这种情况下无论where条件里有没有不等于都不会有影响

    ②参考eg4可知查询列在索引列或主键列的范围之外,索引前导列存在不等于,不走索引

    ③参考eg5可知,查询列在索引列或主键列的范围之外,索引非前导列存在不等于,仍然走索引,此时需要回表,因此extra为ICP。

    ④对比eg5和eg7,两者的执行计划中的extra均为ICP,但key_len和type不同;eg5的非前导列在where条件中存在不等于,因此联合索引中的非前导列create_time并没有被利用到,所以key_len只有99;eg7的非前导列条件where条件中是一个范围,由于是where条件中的第一个范围,因此这个范围可以走索引,所以key_len为105;eg5和eg7之所以都是ICP是因为查询列user_name需要回表

    ⑤参考eg9,当满足覆盖索引条件的时候,即使在where条件中有双范围,仍然会被全部利用到

    ⑥参考eg8,不满足覆盖索引条件时,where条件中只有第一个范围能被索引利用到,是否走索引优化器自身会做权衡,当取值量太大时索引反而不如全表

    ⑦参考eg6,满足覆盖条件时,即使where条件不满足索引的最左规则,语句仍然走了索引只不过type为极为低效的index(全索引扫描),extra显示此时仍然是覆盖索引

    相关文章

      网友评论

        本文标题:where条件中出现了(不等于/多重范围)就一定不走索引了吗

        本文链接:https://www.haomeiwen.com/subject/ftbheqtx.html