如何让mysql索引更快一点

在 InnoDB 中,从二级索引回到主键索引查询数据,这个过程称做回表过程,并且这个回表过程是能够被优化的,这个优化就是利用覆盖索引mysql

先说结论,若是一个索引的字段包含了全部要查询的字段,这个索引就称做覆盖索引,覆盖索引能够减小回表过程,能有效提升查询效率sql

前面咱们有说过,在 InnoDB 中数据都是保存在 B+ 树上,主键索引保存了整行记录,二级索引保存了主键的值。bash

一次查询操做,要么是遍历主键索引,要么是遍历二级索引,要么就是先遍历二级索引获得主键 id 的值,而后再到主键索引上经过主键 id 查找知足要求的记录。测试

若是只遍历一次 B+ 树就能获取到咱们要的数据,即没有回表过程,这个效率显然是不错的,这就是覆盖索引的优点。下面看个具体的例子。优化

mysql> create table user(
id int(11) primary key, 
name varchar(20) not null, 
age int(11),
sex int(11),
index (age)) engine=InnoDB;
复制代码

依然是新建一个表,建立索引,插入一些测试数据,注意这里只是为了解释说明覆盖索引,并不表示 mysql 的真实执行方式,由于会涉及到 mysql 的优化器机制,这里暂且不说了,之后再写。ui

1    bob 16  1
2    kom 19  0
3    gum 18  1
4    tt  20  1
5    yy  25  1
复制代码

建立一个 user 表,给 age 字段添加一个二级索引,并插入上面五条数据,而后看下面这条查询语句。spa

select name from user where age between 18 and 21
复制代码

咱们来分析下这条 sql 的执行过程:设计

1、age 字段上有索引,mysql 会先到 age 字段的 B+ 树上找到知足条件的第一个叶子节点(age=19),这个叶子节点上保存了对应主键 id 的值 2,而后再到主键索引上找到 id 为 2 的这条记录,同时把 name 字段拿出来。code

2、重复第一步的操做,继续从 age 索引上的叶子节点日后遍历找出知足条件的第二个叶子节点,一样回到主键上拿出 name 字段的值,直到遍历到不知足条件的叶子节点(age=25)。索引

也就是说,这条 sql 语句虽然用到了索引,可是 age 索引上并无要查询的 name 字段,因此只能回表到主键索引上查出 name 字段,因此这个过程实际上是遍历了个两个 B+ 树。

那么咱们删除 age 这个单列索引,建立一个覆盖索引 (age,name), 把要查询的 name 字段也添加到索引中来。

#删除原索引
drop INDEX age on USER
#新建覆盖索引
ALTER TABLE USER add index age_name(age,name)
复制代码

因为如今这个覆盖索引上的字段包含了要查询的 age 和 name 字段,免去了到主键索引上查询数据的过程,其实也就是只遍历了一个 B+ 树,能够大大提高查询效率。

添加索引虽然能提高查询效率,但索引也是须要占用额外空间的,并且索引还须要维护成本,因此一般加不加索引须要根据实际需求来权衡。

总之,在设计索引或者优化 sql 语句的时候,要尽可能避免回表操做,因此使用覆盖索引是一种经常使用的 sql 优化手段。

因此咱们平时写 sql 语句的时候,select 后面只写查询须要用到的字段,去掉不须要的字段,避免回表操做。

有问题欢迎你们留言交流,原创不易,若是文章对你有帮助,欢迎点赞,感谢支持。