当前位置:网站首页>MySQL中回表的代价

MySQL中回表的代价

2022-07-06 17:21:00 秀强

回表的代价

对于下面这个查询语句来说:
SELECT * FROM single_ table WHERE key1 > 'a' AND key1 < 'c';
我们可以选择下面这两种方式来执行。

  • 以全表扫描的方式执行该查询
    也就是直接扫描全部的聚簇索引记录,针对每一条聚簇索引记录,都判断搜索条件是否成立,如果成立则发送到客户端,否则跳过该记录。
  • 使用 idx_key1 执行该查询
    可以根据搜索条件 key1>a’ AND key1 < ‘c’ 得到对应的扫描区间(‘a’,‘c’),然后扫描该扫描区间中的二级索引记录。由于 idx_key1 索引的叶子节点存储的是不完整的用户记录,仅包含 key1、id 这两个列,而查询列表是*,这意味着我们需要获取每条二级索引记录对应的聚簇索引记录,也就是执行回表操作,在获取到完整的用户记录后再发送到客户端。

对于使用 InnoDB 存储引擎的表来说,索引中的数据页都必须存放在磁盘中,等到需要时再加载到内存中使用。这些数据页会被存放到磁盘中的一个或者多个文件中,页面的页号对应着该页在磁盘文件中的偏移量。以 16KB 大小的页面为例,页号为 0 的页面对应着这些文件中偏移量为 0 的位置,页号为 1 的页面对立着这些文件中偏移量为 16KB 的位置。
B+树的每层节点会使用双向链表连接起来,上一个节点和下一个节点的页号可以不必相邻。不过在实际实现中,InnoDB 还是尽量让同一个索引的叶子节点的页号按照顺序排列。
也就是说,idx_key1 在扫描区间(‘a’,‘e’)中的二级索引记录所在的页面的页号会尽可能相邻。即使这些页面的页号不相邻,但起码一个页面可以存放很多记录,也就是说在执行完一次页面 I/O 后,就可以把很多二级索引记录从磁盘加载到内存中。总而言之,就是读取在扫描区间(‘a’,‘e’)中的二级索引记录时,所付出的代价还是较小的。不过扫描区间(‘a’,‘e’)中的二级索引记录对应的 id 值的大小是毫无规律的,我们每读取一条二级索引记录,就需要根据该二级索引记录的 id 值到聚簇索引中执行回表操作。如果对应的聚簇索引记录所在的页面不在内存中,就需要将该页面从磁盘加载到内存中。由于要读取很多 id 值并不连续的聚簇索引记录,而且这些聚簇索引记录分布在不同的数据页中,这些数据页的页号也毫无规律,因此会造成大量的随机 I/O。
需要执行回表操作的记录越多,使用二级索引进行查询的性能也就越低,某些查询宁愿使用全表扫描也不使用二级索引。比如,假设 key1 值在 'a’~’c’之间的用户记录数量占全部记录数量的 99% 以上,如果使用 idx_key1 索引,则会有 99% 以上的 id 值需要执行回表操作。这还不如直接执行全表扫描。
那么在执行查询时,什么时候采用全表扫描,什么时候使用二级索引+回表的方式呢?这就是查询优化器应该做的工作。查询优化器会事先针对表中的记录计算一些统计数据,然后再利用这些统计数据或者访问表中的少量记录来计算需要行回表操作的记录数。如果需要执行回表操作的记录数越多,就越倾向于使用全表扫描,反之则倾向于使用二级索引+回表的方式。当然,查询优化器所做的分析工作没有这么简单,但大致上是这样一个过程。
一般情况下,可以给查询语句指定 LIMIT 子句来限制查询返回的记录数,这可能会让查询优化器倾向于选择使用二级索引+回表的方式进行查询,原因是回表的记录越少,性能提开就越高。比如,上面的查询语句可以改写成下面这样:
SELECT * FROM single_table WHERE key1 >'a' AND key1 < 'c' LIMIT 10;
添加了 LIMIT 10 子句后的查询语句更容易让查询优化器采用二级索引+回表的方式来执行。
对于需要对结果进行排序的查询,如果在采用二级索引执行查询时需要执行回表操作的记录特别多,也倾向于使用全表扫描+文件排序的方式执行查询。比如下面这个查询语句:
SELECT * FROM single_table ORDER BY key1;
由于查询列表是 *,如果使用二级索引进行排序,则需要对所有二级索引记录执行回表操作。这样操作的成本还不如直接遍历聚簇索引然后再进行文件排序低,所以查询优化器会倾向于使用全表扫描的方式执行查询。如果添加了 LIMIT 子句,比如下面这个查询语句:
SELECT * FROM single_table ORDER BY key1 LIMIT 10;
这个查询语句需要执行回表操作的记录特别少,查询优化器就会倾向于使用二级索引+回表的方式来执行。

原网站

版权声明
本文为[秀强]所创,转载请带上原文链接,感谢
https://blog.csdn.net/AlphaBr/article/details/125590440