写点什么

1 分钟带你学会 MySQL 覆盖索引,让你的 SQL 更高效

作者:程序员拾山
  • 2023-01-16
    河南
  • 本文字数:1002 字

    阅读完需:约 3 分钟

覆盖索引是 MySQL 优化 sql 性能的一种非常重要而且常用的手段,通过覆盖索引,我们可以直接查询到需要的结果,而不用回表,从而大大减少树的搜索次数,非常明显的提升查询性能。

1,数据如何存储与查找


我们知道,MySQL 的数据都是存储在 B+树上的,每一个索引都代表一个 B+树。


对于主键索引,叶子节点存储的是一行记录的所有字段值(逻辑上),而非主键索引的叶子节点存储的是主键值,非叶子节点存储的是索引以及指向数据的指针。


那我们查询数据的时候,MySQL 是如何执行的呢?


以主键索引为例,就是在主键索引树上,从根节点出发,一直向下查找,直到找到符合条件的记录。

如果我们要查下图中的 User2 节点,那么查找路径就是 UserA->UserC->UserF->User2。


2,回表


只按照主键查询是一种理想中的状态,随着业务逐渐复杂,表中的字段会越来越多,我们也会建立更多的非主键索引以应对业务带来的挑战。


但是非主键索引会带来一个问题:回表。


以下面这条 sql 为例:

select * from t where m in (3,4);
复制代码


我们在表 t 的 m 字段上设置一个索引,那么这条 sql 的执行流程就是:


1,在索引树 m 上,找到记录 3,获取到主键 id,比如 id=100;


2,拿着 100 这个 id 去主键索引树上,获取到这一行的数据;


3,在索引树 m 上,找到记录 4,获取到主键 id,比如 id=101;


4,拿着 101 这个 id 去主键索引树上,获取到这一行的数据;


5,在索引树上查找下一个记录 5(不一定是 5,这里的 5 只是代表记录 4 后面的一条记录),记录 5 不符合查询条件,结束查询。


在上面的流程中,步骤 2,4 代表了回主键索引树搜索,这个动作就叫做回表。


而 MySQL 之所以做回表这个动作,是因为我们要查的数据 select *,只有在主键索引树上才有,所以不得不回表查询。

3,覆盖索引


如果我们把上面的 sql 改成下面这样:


select id from t where m in (3,4);
复制代码


这个时候只需要查询 id 就行,而 id 这个值已经在 m 索引树上了,这时就不用再回表了,可以直接提供查询结果。


可以说,索引 m 覆盖了我们的查询请求,这种情况我们就称为覆盖索引。


这也是为什么我们在很多 MySQL 规范中可以看到,要求我们查询数据时尽量避免"select *",就是因为"select *"会导致覆盖索引失效,从而引起强制回表,sql 性能可能大幅下降。

4,最后


在我们查询 sql 时,我们不仅要考虑 where 条件是否匹配了索引,还要尽量考虑查询的字段是否可以通过索引直接获取,覆盖索引可以减少树的搜索次数,显著的提升 sql 查询性能。




我是 @程序员拾山,欢迎关注我,期待与大家一起学习成长,也感谢您的点赞和关注。

发布于: 刚刚阅读数: 5
用户头像

JAVA技术分享,全网同名 2019-06-19 加入

学习如逆水行舟,不进则退

评论

发布
暂无评论
1分钟带你学会MySQL覆盖索引,让你的SQL更高效_MySQL_程序员拾山_InfoQ写作社区