MySQL系列-优化之覆盖索引

1.什么是覆盖索引

我们知道MySQL的B+Tree索引是用我们字段的数据来建立索引的,比如说我们的主键id字段,就是用所有的id来组织这颗索引树,如果我们再对name字段建立索引的话,这个二级索引就是用name字段的数据来组织这颗索引树。那么问题就来了,我们知道对于二级索引而言他的叶子节点存储了对应数据行的id(MySQL系列-B+Tree索引详解),也就是说最后我们的查询还是要通过主键id来进行查询获取数据。如果我们只需要name这个字段呢?比如说 select name from table where name>'aaa'; 我们这个二级索引上保存了的name字段的所有数据,那么就没有必要再通过id去访问数据行了,直接从索引上获取数据即可。称之为覆盖索引,有的也翻译为索引覆盖。

2.explain判断是否覆盖索引

我们可以通过expalin来判断查询是否覆盖索引,主要看extra字段是否有 using index 。

比如说:我们有以下表:

对name字段建立索引:

执行sql 【explain select name from tb where name>'w'】;

可以看到我们使用上了索引idx_name,而且extra字段也出现了using index,说明我们这次查询是覆盖索引的。

把sql稍微修改一下:【explain select id,name from tb where name>'w'】;

可以看到这次查询还是覆盖索引,因为我们二级索引树的叶子节点就保存了对应数据行的id,所以对于二级索引而言,查询的时候加不加id都不影响是否是覆盖索引,id也在二级索引树上。

我们再把sql修改一下:【explain select name,age from tb where name>'w'】;

我们对name字段建立的索引上并没有保存age这个字段的数据,也就无法从索引上来获取数据了,只能访问数据表了。extra字段也没有出现 using index 。

那么我们的业务需求就是经常的查询name和age字段咋办呢?为了再次提高效率我们可以对name和age字段建立复合索引。

例如:

我们再次执行【explain select name,age from tb where name>'w'】

发现我们的新索引并没有使用上,因为我们MySQL优化器认为不值得调用这个复合索引,因为索引也占空间,在当前就10条数据量,表就三个字段(id,name,age)的情况下,他认为多一次主键查询比从复合索引上获取数据的效果更好,而且也使用上了对name字段建立的单值索引。

我们把索引idx_name删掉,在次执行【explain select name,age from tb where name>'w'】

这个时候MySQL乖乖用上了我们建立的复合索引,而且extra字段也出现了 using index 。

在一个系统应用当中除非特别情况,否则我们也一般也是建立复合索引。

猜你喜欢

转载自blog.csdn.net/ufo___/article/details/81162087