使用数据库建立索引是必不可少的,面试中也会经常遇到一些有关于索引的问题,常见的就是问 Mysql什么时候会造成索引失效,一般回答就是没有遵守 b+ 树的最左原则,也有遇到过明明已经遵守了但是通过分析函数显示并没有走索引,这里就是使用 order by 有走索引的情况也有不走索引的情况。
建表语句
create table tag
(
id bigint auto_increment comment 'id' primary key,
tagName varchar(256) null comment '标签昵称',
userId varchar(256) null comment '用户id',
parentId bigint null comment '父标签',
isParent tinyint null comment '0-不是 1-是',
createTime datetime default CURRENT_TIMESTAMP null comment '创建时间',
updateTime datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP,
isDelete tinyint default 0 not null comment '是否删除',
)
create index idx_userId on tag (userId);
很平常的建表语句userId有建立索引,查询语句:select * from tag order by userId
通过分析语句查看执行计划如下
从上面的图中可以看出使用order by 索引字段是进行的全表扫描索引并没有走索引,但是使用下面这条sql 又会走索引。
分析
造成这种情况出现主要是因为索引树的原因
当查询字段为 '*' 的时候,虽然可以直接通过 userId字段找到对应的叶子结点数据,但是在返回之前还得拿着这个去进行回表查询,表中有非索引字段进行回表查询,但是由于数据量并不是很大(1000条),所以 Mysql就会直接把所有的数据扫描一遍然后拿到内存中进行排序,这样就不用进行回表的操作。
当查询字段为 对应索引字段时候,可以直接通过索引拿到对应的返回字段,不需要进行回表操作,少了这一步操作速度就很快了,再加上 b+ 树的叶子结点是已经排好序的了,也不需要进行排序的操作。少了这两部操作 mysql就会去走索引了。
总结
需要判断查询的返回字段是否被索引覆盖, 如果全部被索引覆盖了那么就会走索引,如果没有全部覆盖mysql 就会根据数据量的大小来判断是否进行全表扫描或者先走索引再回表查询