MySQL优化器特性(二)MRR优化

俊达2年前技术文章1438

Index Range Scan

索引范围扫描的一般步骤:

1、根据where条件,从B+树定位到第一条记录。

2、从索引页子节点中获取到行号(rowid),根据rowid回表查询数据。

3、使用额外的where条件过滤记录,若满足条件,将记录返回给客户端。

不同的存储引擎,rowid和表的存储格式可能会有差异。比如在MyISAM中,rowid记录的是记录在文件中的偏移量,实际的表中,不需要额外存储rowid。在InnoDB中,rowid就是表的主键,表存储为聚簇索引。

index_range_scan.png


使用索引范围扫描(Index Range Scan)时,按顺序获取的记录ID(rowid)在表中是无序的,当有大量记录需要回表查询时,可能会产生大量随机IO,影响数据库性能。


针对这种场景,MySQL设计了DSMRR(Disk Sweep Multi-range Read)访问路径,在回表查询记录前,先将从索引中获取到的rowid存放在MRR buffer中,并按rowid进行排序,然后按rowid的顺序回表查询数据。


MRR优化的例子

满足一定的条件后,优化器才会使用MRR优化,出于演示的目的,我们给查询添加Hint。

测试表结构:

mysql> show create table tb\G
*************************** 1. row ***************************
       Table: tb
Create Table: CREATE TABLE `tb` (
  `a` int DEFAULT NULL,
  `b` int DEFAULT NULL,
  `c` int DEFAULT NULL,
  `id` int NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`),
  KEY `idx_c` (`c`),
  KEY `idx_ab` (`a`,`b`)
) ENGINE=InnoDB AUTO_INCREMENT=321 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

MRR hint:

mysql> explain select /*+ MRR(tb) */ *  from tb where a < 2\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tb
   partitions: NULL
         type: range
possible_keys: idx_ab
          key: idx_ab
      key_len: 5
          ref: NULL
         rows: 32
     filtered: 100.00
        Extra: Using index condition; Using MRR
1 row in set, 1 warning (0.00 sec)

Extra中显示“Using MRR”,说明采用了MRR优化。


不加Hint时,没有使用MRR优化:

mysql> explain select  *  from tb where a < 2\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tb
   partitions: NULL
         type: range
possible_keys: idx_ab
          key: idx_ab
      key_len: 5
          ref: NULL
         rows: 32
     filtered: 100.00
        Extra: Using index condition
1 row in set, 1 warning (0.00 sec)


使用BKA hint也会使用MRR优化

mysql> explain select /*+ BKA(tb) */ *  from tb where a < 2\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tb
   partitions: NULL
         type: range
possible_keys: idx_ab
          key: idx_ab
      key_len: 5
          ref: NULL
         rows: 32
     filtered: 100.00
        Extra: Using index condition; Using MRR
1 row in set, 1 warning (0.01 sec)


MRR执行过程

1、根据where条件,定位索引range。

2、获取rowid,先存放到MRR buffer中。

3、根据rowid对MRR buffer进行排序。

4、按rowid的顺序回表获取数据。

5、根据where条件中的额外条件过滤数据,若满足条件,将数据返回给客户端。

按rowid的顺序回表获取数据,可能能在一定程度上提升数据库缓存的命中率,减少磁盘随机IO。


mrr-buffer.jpg


使用MRR的条件

查询需要满足以下几个条件,优化器才会使用MRR优化:

1、使用了索引范围执行计划(range),非覆盖索引,非Primary Key。如果查询本身没有使用索引范围扫描的执行计划,就无法使用MRR优化。如果查询用了覆盖索引,不需要回表,或者是在InnoDB的主键上进行范围扫描,都不需要使用MRR优化。

2、表占用的空间超过一定大小时,才会使用MRR优化。对于InnoDB,表的大小超过InnoDB buffer pool,对于MyISAM,表的大小超过100M,优化器才会考虑使用MRR优化。

3、range查询预估需要访问的记录数超过一定数量,才会考虑使用MRR优化。如果预估需要访问的记录数不多,则不会考虑使用MRR优化。8.0.32版本中这个值是50。

4、optimizer_switch,开启MRR。默认情况下mrr和mrr_cost_based都是开启的。

5、如果optimizer_switch mrr_cost_based=on,则优化器会评估MRR执行计划的成本,只有当MRR的成本比默认range访问的成本更低时,才会使用MRR优化。

6、如果给查询添加MRR或BKA提示,则只需要满足条件1就可以使用MRR优化。当然一般情况下不建议使用这几个Hint。让优化器自动选择就可以了。


如何确定MRR buffer大小

MRR buffer大小的上限由参数read_rnd_buffer_size决定。如果优化器评估出来range需要访问的记录数较小,则实际分配的buffer可能会比read_rnd_buffer_size小,会按需分配buffer(记录数 * 单条ROWID占用的空间)。


相关文章

MySQL运维实战(5.1) 字符和编码的基本概念

MySQL运维实战(5.1) 字符和编码的基本概念

字符和编码字符字符是符号,是人们用于交流的各类符号,如26个英文字母、汉字、标点符号、数学运算符、其他语言的字母和符号。编码编码是计算机中以二进制方式存储字符的方式。字符集字符集是字符和编码的映射表。...

MySQL运维实战(7.2) MySQL复制server_id相关问题

MySQL运维实战(7.2) MySQL复制server_id相关问题

主库server_id没有设置主库没有设置server_idGot fatal error 1236 from master when&nb...

MySQL优化器特性(五)单表访问路径

数据库的访问路径(access path)是指从表中获取数据的方式,一般可以通过扫描表或通过索引获取数据。想熟练掌握SQL优化技能,首先需要熟悉单表访问路径。本文先简单介绍MySQL支持的各种单表访问...

MySQL运维实战(2)MySQL用户和权限管理

MySQL用户管理基本命令创建用户使用create user命令创建用户create user 'username'@'host' ide...

MySQL运维实战(4.5) SQL_MODE之NO_ZERO_DATE和NO_ZERO_IN_DATE

NO_ZERO_DATE:日期中不允许'0000-00-00'NO_ZERO_IN_DATE:日期中年、月或日不允许为0,如不允许'2021-00-01', '...

MySQL运维实战(2.3)MySQL的权限体系和一个例子

mysql权限按授权范围分为3大类全局权限。全局权限是用于管理系统模块的权限。跟具体的数据库或对象无关。授权时需要指定为*.*数据库权限对象权限对于具体的数据库对象的权限,如表、字段级别的权限。MyS...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。