当前位置: 首页 > 科技观察

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

时间:2023-03-12 17:21:31 科技观察

覆盖索引是MySQL优化SQL性能的一个非常重要且常用的方法。回表,从而大大减少了树的搜索次数,显着提高了查询性能。数据是如何存储和查找的我们知道MySQL数据是存储在B+树上的,每个索引代表一棵B+树。对于主键索引,叶子节点存储一行记录的所有字段值(逻辑上),而非主键索引的叶子节点存储主键值,非叶子节点存储索引和指向数据的指针。当我们查询数据时,MySQL是如何执行的呢?以主键索引为例,在主键索引树上,从根节点开始向下查找,直到找到满足条件的记录。如果我们要查看下图中的User2节点,搜索路径为UserA->UserC->UserF->User2。只根据主键查询表是一种理想状态。随着业务越来越复杂,表中的字段会越来越多,我们也会建立更多的非主键索引来应对业务带来的挑战。但是非主键索引会带来一个问题:回表。以下面的sql为例:select*fromtwheremin(3,4);我们在表t的m字段上设置了一个索引,那么这条sql的执行过程就是:在索引树m上查找记录3.获取主键id,比如id=100;将100的id带到主键索引树中,得到这一行的数据;在索引树m上查找记录4,获取主键id,如id=101;将101的id带到主键索引树中,得到这一行的数据;在索引树上找到下一条记录5(不一定是5,这里5只是代表记录4之后的一条记录),记录5不满足查询条件,结束查询。上述过程中,第2步和第4步代表向主键索引树回溯,这个动作称为回表。MySQL之所以做回表这个动作,是因为我们要查的数据select*只有在主键索引树上才有,所以要回表查询。覆盖索引如果我们把上面的sql改成下面这样:selectidfromtwheremin(3,4);这个时候我们只需要查询id,id的值已经在m索引树上了,所以这个时候不需要再返回表,直接提供查询结果即可。可以说索引m覆盖了我们的查询请求。在这种情况下,我们称之为覆盖索引。这也是为什么我们在很多MySQL规范中可以看到,在查询数据的时候,要求我们避免使用“select*”,因为“select*”会导致覆盖索引失效,从而导致强行回表,SQL性能可能会大幅下降。最后,我们在查询SQL的时候,不仅要考虑where条件是否匹配索引,还要尽量考虑是否可以直接通过索引获取查询到的字段。覆盖索引可以减少树搜索的次数,显着提高SQL查询性能。