索引的种类

117 阅读3分钟

一、聚簇索引、非聚簇索引

  • 聚簇索引(Clustered Index):又称为聚集索引。将数据存储与索引放到了一起。索引结构的叶子节点保存了行数据必须有而且只能有一个
  • 非聚簇索引(Secondary Index):又称为非聚集索引、二级索引。将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键。可以存在多个这种索引。

聚簇索引选取规则

  1. 如果表中存在主键,那么主键就是聚簇索引。
  2. 如果不存在主键,将使用第一个唯一(unique)索引作为聚簇索引。
  3. 如果表没有主键,也没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚簇索引。

回表查询

通过二级索引找到对应的主键值,再到聚簇索引中查找整行数据,这个过程就是回表查询。

二、覆盖索引

覆盖索引是指查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到。

  • 使用ID查询,直接走聚集索引查询,一次索引扫描,直接返回数据,性能高。
  • 如果返回的列中没有创建索引,有可能会触发回表查询,尽量避免使用select *.

大家看下面的例子:

idnamegendercreatedate
2Arm12021-01-01
3Lily02021-05-21
5Rose02021-02-14
6Zoo12021-06-01
8D0c12021-04-08
  • id是主键,默认是主键索引。
  • name字段是普通索引。

1. select * from tb_user where id = 1;

覆盖索引,因为id为聚簇索引,索引树中叶子节点保存的整行数据。

2. select id,name from tb_user where name = 'Arm';

覆盖索引,因为name的索引树中,叶子节点存储的是主键id的值,索引本身存储的name字段的值。所以通过普通索引name就可以把id,name的信息都查询出来。

3. select id,name,gender from tb_user where name = 'Arm';

非覆盖索引,因为需要分两步执行。 一、通过name索引得到id,name。二、需要进行回表查询,通过id主键索引查询到gender列。

MySQL超大分页优化处理

在数据量比较大时,如果进行limit分页查询,在查询时,越往后,分页查询效率越低。

看一下执行limit分页查询耗时对比:

1691156745889.jpg 因为当在进行分页查询时,如果执行limit 9000000,10,需要MySQL排序前9000010条记录,仅仅返回9000000~9000010的记录,其他记录丢弃,查询排序的代价非常大。

优化思路

分页查询时,通过创建覆盖索引能够比较好的提高性能。可以通过覆盖索引+子查询方式进行优化。

select * 
from tb_sku t, 
(select id from tb_sku order by id limit 9000000,10)a
where t.id = a.id;

这条sql中,子查询通过id进行排序以及查到9000000~9000010条记录都是通过id覆盖索引,这里效率就比较高了,而且又通过id覆盖索引查询整行数据。