MRR,全称「Multi-Range Read Optimization」。

简单说:MRR 通过把「随机磁盘读」,转化为「顺序磁盘读」,从而提高了索引查询的性能。

至于:

  • 为什么要把随机读转化为顺序读?
  • 怎么转化的?
  • 为什么顺序读就能提升读取性能?

咱们开始吧。

磁盘:苦逼的底层劳动人民

执行一个范围查询:

mysql 

当这个 sql 被执行时,MySQL 会按照下图的方式,去磁盘读取数据(假设数据不在数据缓冲池里):

图中红色线就是整个的查询过程,蓝色线则是磁盘的运动路线。

这张图是按照 Myisam 的索引结构画的,不过对于 Innodb 也同样适用。

对于 Myisam,左边就是字段 age 的二级索引,右边是存储完整行数据的地方。

先到左边的二级索引找,找到第一条符合条件的记录(实际上每个节点是一个页,一个页可以有很多条记录,这里我们假设每个页只有一条),接着到右边去读取这条数据的完整记录。

读取完后,回到左边,继续找下一条符合条件的记录,找到后,再到右边读取,这时发现这条数据跟上一条数据,在物理存储位置上,离的贼远!

咋办,没办法,只能让磁盘和磁头一起做机械运动,去给你读取这条数据。

第三条、第四条,都是一样,每次读取数据,磁盘和磁头都得跑好远一段路。

磁盘的简化结构可以看成这样:

可以想象一下,为了执行你这条 sql 语句,磁盘要不停的旋转,磁头要不停的移动,这些机械运动,都是很费时的。

10,000 RPM(Revolutions Per Minute,即转每分) 的机械硬盘,每秒大概可以执行 167 次磁盘读取,所以在极端情况下,MySQL 每秒只能给你返回 167 条数据,这还不算上 CPU 排队时间。

上面讲的都是机械硬盘,SSD 的土豪,请随意 - -

对于 Innodb,也是一样的。 Innodb 是聚簇索引(cluster index),所以只需要把右边也换成一颗叶子节点带有完整数据的 B+ tree 就可以了。

顺序读:一场狂风暴雨般的革命

到这里你知道了磁盘随机访问是多么奢侈的事了,所以,很明显,要把随机访问转化成顺序访问:

mysql 

我们开启了 MRR,重新执行 sql 语句,发现 Extra 里多了一个「Using MRR」。

这下 MySQL 的查询过程会变成这样:

对于 Myisam,在去磁盘获取完整数据之前,会先按照 rowid 排好序,再去顺序的读取磁盘。

对于 Innodb,则会按照聚簇索引键值排好序,再顺序的读取聚簇索引。

顺序读带来了几个好处:

1、磁盘和磁头不再需要来回做机械运动;

2、可以充分利用磁盘预读

比如在客户端请求一页的数据时,可以把后面几页的数据也一起返回,放到数据缓冲池中,这样如果下次刚好需要下一页的数据,就不再需要到磁盘读取。这样做的理论依据是计算机科学中著名的局部性原理:

当一个数据被用到时,其附近的数据也通常会马上被使用。

3、在一次查询中,每一页的数据只会从磁盘读取一次

MySQL 从磁盘读取页的数据后,会把数据放到数据缓冲池,下次如果还用到这个页,就不需要去磁盘读取,直接从内存读。

但是如果不排序,可能你在读取了第 1 页的数据后,会去读取第2、3、4页数据,接着你又要去读取第 1 页的数据,这时你发现第 1 页的数据,已经从缓存中被剔除了,于是又得再去磁盘读取第 1 页的数据。

而转化为顺序读后,你会连续的使用第 1 页的数据,这时候按照 MySQL 的缓存剔除机制,这一页的缓存是不会失效的,直到你利用完这一页的数据,由于是顺序读,在这次查询的余下过程中,你确信不会再用到这一页的数据,可以和这一页数据说告辞了。

顺序读就是通过这三个方面,最大的优化了索引的读取。

别忘了,索引本身就是为了减少磁盘 IO,加快查询,而 MRR,则是把索引减少磁盘 IO 的作用,进一步放大。

一些关于这场革命的配置

和 MRR 相关的配置有两个:

  • mrr: on/off
  • mrr_cost_based: on/off

第一个就是上面演示时用到的,用来打开 MRR 的开关:

mysql > set optimizer_switch='mrr=on';

如果你不打开,是一定不会用到 MRR 的。

另一个,则是用来告诉优化器,要不要基于使用 MRR 的成本,考虑使用 MRR 是否值得(cost-based choice),来决定具体的 sql 语句里要不要使用 MRR。

很明显,对于只返回一行数据的查询,是没有必要 MRR 的,而如果你把 mrr_cost_based 设为 off,那优化器就会通通使用 MRR,这在有些情况下是很 stupid 的,所以建议这个配置还是设为 on,毕竟优化器在绝大多数情况下都是正确的。

另外还有一个配置 read_rnd_buffer_size ,是用来设置用于给 rowid 排序的内存的大小。

显然,MRR 在本质上是一种用空间换时间的算法。MySQL 不可能给你无限的内存来进行排序,如果 read_rnd_buffer 满了,就会先把满了的 rowid 排好序去磁盘读取,接着清空,然后再往里面继续放 rowid,直到 read_rnd_buffer 又达到 read_rnd_buffe 配置的上限,如此循环。

另外 MySQL 的其中一个分支 Mariadb 对 MySQL 的 MRR 做了很多优化,有兴趣的同学可以看下文末的推荐阅读。

尾声

你也看出来了,MRR 跟索引有很大的关系。

索引是 MySQL 对查询做的一个优化,把原本杂乱无章的数据,用有序的结构组织起来,让全表扫描变成有章可循的查询。

而我们讲的 MRR,则是 MySQL 对基于索引的查询做的一个的优化,可以说是对优化的优化了。

要优化 MySQL 的查询,就得先知道 MySQL 的查询过程;而要优化索引的查询,则要知道 MySQL 索引的原理。

就像之前在「如何学习 MySQL」里说的,要优化一项技术、学会调优,首先得先弄懂它的原理,这两者是不同的 Level。

以上(此处应该有点赞).

推荐阅读:

  • MySQL MRR
  • Mariadb MRR
  • MySQL索引背后的数据结构及算法原理
  • MySQl MRR 源码分析

mysql为什么每天0点就装东西_MySQL 的 MRR 到底是什么?相关推荐

  1. mysql为什么每天0点就装东西_MySQL的详细安装教程

    1.安装之前需要注意的几点 建议不要安装最新版本,一般找mysql5.0系列版本即可: mysq1官网有.zip和.msi两种安装形式: zip是压缩包,直接解压缩以后使用的,需要自己配置各种东西:m ...

  2. RHEL 7.8 64bit MYSQL linux-generic 8.0.20 初始化安装

    1. 准备最基础信息的my.cnf本案例my.cnf配置文件是最基础的初始化配置文件,只能保证mysql服务正常开启,并不适用生产环境, 关于更多关于buffer.logfile等性能参数需要根据主机 ...

  3. iis7.0下载iis7.0安装包下载iis7.0 xp xp装iis7.0

    IIS 7.0是今年稍后将推出的最让我激动不已的产品之一.它是自IIS 1.0之后我们所做过的最重大的web服务器发布,它将为管理人员和开发人员引入不计其数的改进. IIS开发团队的Mike Volo ...

  4. MySQL Workbench 8.0 CE数据库管理基本操作

    该笔记的目的是带领已经了解过MySQL命令行语法的读者初次接触MySQL Workbench 8.0 CE,并用图形界面简化数据库创建.数据表创建.插入数据等操作. 操作流程 打开"MySQ ...

  5. 解决使用Navicat等工具进行连接登录mysql的1130错误,无法使用Ip远程连接的问题(mysql为8.0版本)

    解决使用Navicat等工具进行连接登录mysql的1130错误,无法使用Ip远程连接的问题(mysql为8.0版本) 参考文章: (1)解决使用Navicat等工具进行连接登录mysql的1130错 ...

  6. mysql sum 为 0 的解决方法

    mysql sum 为 0 的解决方法 参考文章: (1)mysql sum 为 0 的解决方法 (2)https://www.cnblogs.com/huanghuanghui/p/9338037. ...

  7. 利用MySQL Cluster 7.0 + LVS 搭建高可用环境

    1.前言 随着数据量规模的扩大,企业对 MySQL 的要求就不仅仅是能用了,也在寻求各种高可用方案.以前我们的大部分高可用方案其实还存在一定缺陷,例如 MySQL Replication 方案,Mas ...

  8. CLR 4.0 有哪些新东西? -- 类型等价

    CLR 4.0 有哪些新东西? -- 类型等价 我上篇博文说到了CLR 4.0类型嵌入特性, 那么请大家想一想类型嵌入是谁实现的? 选项A   CLR    选项B  编译器  选项C TlbImp  ...

  9. mysql awr v1.0.1发布

    现发布mysql awr v1.0.1 修复问题: 1.galera cluster下flush table/index_statistcs时如果系统中业务ddl频繁可能会导致很多进程处于prepar ...

最新文章

  1. [BSidesSF2020]decrypto-1
  2. Netty - 传输
  3. python程序的基本框架_Python PyQt学习随笔:PyQt主程序的基本框架
  4. 【Ubuntu-Opencv】Ubuntu14.04 Opencv3.3.0 使用中出现OpenCV Error: Unspecified error
  5. 函数无法识别_PostgreSQL找不到最佳函数问题解析
  6. final、finally和finalize;throw和throws;collection和collections;==和equals;Statement和PrepareStatement...
  7. P1350 车的放置
  8. Navicat连接MySQL8.0版本时出现Client does not support authentication protocol requested by server;报错的问题解决办法
  9. jq控制div是否展示_jQuery判断一个元素是否可见的方法
  10. 5款非常好用的免费数据库建模工具(免费)
  11. 舵机控制 —— 一篇就够
  12. 【Google】“共码未来“—2022谷歌开发者大会参会记录
  13. 解决尝试连接“ECONNREFUSED - 连接被服务器拒绝”失败的问题
  14. 人人都在推销(销售永不为“奴”)
  15. Gym - 100889H Hitting Points 计算几何+三分+二分
  16. TensorFlow高阶张量叉乘
  17. cpu第几代计算机,赛扬G系列有几代cpu分别是
  18. 数据库中五个Key(鍵)的概念区分
  19. 汇编语言---指令格式和基本语法
  20. 2018中国智造金长城奖:创新能力与行业竞争力并重

热门文章

  1. python 访问网页aspx_asp.net – 如何向python中的.aspx页面提交查询
  2. postman跨域测试_安装使用Hoppscotch构建API请求访问与测试
  3. 省选+NOI 第八部分 数论
  4. P5737 【深基7.例3】闰年展示(python3实现)
  5. NOI题库 python题解-2022.01.07整理(1.1-1.3)
  6. ThinkPHP框架在linux服务器nginx环境下跑出现溢出缓存问题解决方法
  7. STM32H743-梳理ADC模数转换器在CubeMX上的配置
  8. 大数据概论ppt_解读 | 货拉拉搬家大数据报告(30页PPT干货)
  9. 手把手带你入门Python爬虫(五、CSDN论坛之模型设计)
  10. python编辑器_资深程序员:学Python我推荐你用这几款编辑器