mysql联合索引包含>=是为何能继续匹配后续字段?

create table study_demo.transaction_demo
(
    id int auto_increment comment 'id'
        primary key,
    user_name varchar(20) collate utf8_unicode_ci not null,
    user_id int default 0 not null,
    info int default 0 not null comment 'info',
    info2 int default 0 not null comment 'info2'
)comment '事务demo' charset=utf8;
create index transaction__user_info_demo__index
    on study_demo.transaction_demo (user_id, info2, user_name);

执行计划:

explain select * from transaction_demo 
where user_id = 2 and info2 > 1 and user_name like 'demo%';
key:transaction__user_info_demo__index
key_len:8

推算出命中了user_id,info2字段

执行计划:

explain select * from transaction_demo 
where user_id = 2 and info2 >= 1 and user_name like 'demo%';
key:transaction__user_info_demo__index
key_len:70

推算出命中了user_id,info2,user_name字段

阅读 2.4k
3 个回答
知数堂《乱弹MySQL》第十二讲《12、相似的SQL执行计划key_len为什么不同》解释了这个问题,对于数字型的联合索引,最左边的列的是否有等号非常重要,直接决定key_len的大小
https://blog.csdn.net/n88Lpo/...

个人理解,条件判断大于等于,MySQL直接定位到索引节点上,该节点和之后的节点都符合条件;如果条件判断是大于,还需要移动指针,不利于索引使用

对于int类型,如果条件>x,建议改成>=x+1

联合索引的匹配规则,加入有如下联合索引:
(a,b,c,d)

索引匹配规则是以从前往后,顺序优先的,也就是最左原则。
可以匹配到索引:
a, a,b, a,b,c, a,b,c,d
从这里看到规律了吧,如果匹配
b, c, d, b,c,d这种字段是根本没法用索引的。

所以要查询的话,where的匹配字段要按照这个索引顺序从左到右的顺序写查询条件,只要逻辑条件符合这个最左匹配原则,那么索引都能用得上,如果你要问为什么,这个就涉及到数据结构上面的东西了,描述的话不好描述,画图的话我又懒得画,记住这个规则就行了。

新手上路,请多包涵

我思来想去,觉得是这样的。>=在 mysql 查询优化器当中,会将一条 sql 拆分为两条,然后 union all 组合起来。一个是=查询,这个可以走索引,也就是 key_len 比较长的原因。另一条是>,后续的字段不走索引,此时 key_len 比较短。因此从结果上看 key_len 长,但实际上效率并没有高出来。也就是说 > 1 和 >=2 在效率上其实没什么差别。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题