索引就像书的目录一样,可以帮助数据库快速定位到数据所在的位置。

索引

MySQL中,InnoDB存储引擎的索引使用B+数数据结构实现,具体结构如下:

InnoDB索引结构

有以下特点:

  • 数据文件本身就是索引文件
  • 数据按照主键顺序组织和存储,因此InnoDB要求表必须有主键,如果没有指定主键或唯一键,则自动生成一个长度为6个字节的隐式长整型字段来作为主键,主键索引称聚簇索引
  • 所以非主键索引的数据域都会存储主键ID,除了联合索引外,其他的耳机索引的数据域存储的就是主键ID
  • 使用主键搜索数据非常高效,但是使用其他索引有可能会需要回表

回表

在使用主键查询的时候,由于主键索引上的数据域存储了该条数据的完整内容,所以能够直接将数据取出来。但是当使用非主键索引,如二级索引查询数据时,索引上数据域只存储了该条数据对应的主键,为了拿到完整的数据,还需要使用主键的值回到表中去查询数据,这个过程就称为回表。在InnoDB中,除非索引上已经包含了查询所需要的完整数据,否则都会使用ID进行回表查询。

覆盖索引

在InnoDB中,创建索引可以包含多个字段,比如(name, age),这种索引叫做联合索引。联合索引中,当索引的字段中已经完全包含需要的字段时,就叫做覆盖索引。覆盖索引在查询的时候,因为数据域的字段已经满足查询要求,因此不会回表,减少了一般索引的回表操作,提高查询的性能。不过索引所占用的空间就变大了,属于是以空间换时间的类型。

索引下推优化

索引下推,英文Index condition pushdown,简称ICP,是在MySQL5.6退出的特性,和覆盖索引一样,也是用来优化查询的。且索引下推优化只对联合索引才会有效。

考虑这样一个场景:

1
select * from tb_test where name like 'J%' and age > 10;

假设在表上存在(name, age)这样一个联合索引,在5.6之前,存储引擎根据索引查找到name以J开头的数据后将数据返回给MySQL服务器,服务器判断数据是否符合条件。在5.6之后,因为使用了索引下推优化,MySQL服务器将查询数据的条件发送给InnoDB存储引擎,存储引擎会判断数据是否符合条件,然后检索出数据,将符合条件的数据返回给MySQL服务器。也就是说在判断了name以J开头的数据之后,还会在继续判断age是否大于10,最后再将符合条件的数据返回给MySQL服务器。索引下推减少了回表的次数,也减少了MySQL服务器从存储引擎接收数据的次数或者大小。