MySQL特性:MRR,Multi-Range Read,多范围读

孔个个
MRR在5.6版本开始支持,相关文章不少。但是读起来层次感差了一些,在这里我用自己的理解重新整理了一版。
这里参考了很多在网络上能找到的资料,才使我更全面的理解MRR,但时间有些久,并未记录出处,且多数文字并非原文,在此感谢所有默默分享知识的大佬们。

5.6以上版本开始支持MRR

基于辅助/第二索引的查询时,将随机 IO 转化为顺序 IO 以降低查询过程中 IO 开销的一种手段,这对IO-bound类型(IO密集型)的SQL语句性能带来极大的提升,适用于range ref eq_ref类型的查询。

MRR原理

查询辅助索引时,首先把查询结果按照主键进行排序,按照主键的顺序进行书签查找,避免频繁发生离散读操作导致缓冲区中的页被替换出缓冲区,然后又不断的被新的请求读入缓冲区,减少缓冲池中页被替换的次数。

  • 将查询到的辅助索引结果放在一个buffer中(read_end_buffer_size)
  • 将buffer中的辅助索引根据主键(rowid)进行排序
  • 再根据上述排序后的主键(rowid)顺序,(回表)读取数据

MRR效果,MRR带来的好处

  • 减少磁盘随机IO访问,将随机IO访问转变成顺序IO访问,提高IO读性能
  • 减少buffer pool中页面被替换的次数

    如果存储引擎(不仅仅是InnoDB)的缓冲池不是足够大,即:不能存放下一张表中的所有数据,此时频繁的发生离散读操作会导致缓冲区中的页被替换出缓冲区,然后又不断的被新的请求读入缓冲区。 若按照主键顺序进行访问,则可以将此重复行为降到最低。

  • 可批量处理对索引的查询操作

  • 在没有使用MRR特性时

    不使用MRR之前(MySQL5.6之前),先根据where条件中的辅助索引获取辅助索引与主键的集合,再通过主键来获取对应的值。辅助索引获取的主键来访问表中的数据会导致随机的IO(辅助索引的存储顺序并非与主键的顺序一致),随机主键不在同一个page里时会导致多次IO和随机读。

  • 先根据where条件中的辅助索引获取辅助索引与主键的集合,结果集为rest
select key_column, pk_column from tb where key_column=x order by key_column
  1. 通过第一步获取的主键来获取对应的值
for each pk_column value in rest
do:
    select non_key_column from tb where pk_column=val
  • 使用MRR特性时

    使用MRR优化(MySQL5.6之后),先根据where条件中的辅助索引获取辅助索引与主键的集合,再将结果集放在buffer(read_rnd_buffer_size 直到buffer满了),然后对结果集按照pk_column排序,得到有序的结果集rest_sort。最后利用已经排序过的结果集,访问表中的数据,此时是顺序IO。即MySQL 将根据辅助索引获取的结果集根据主键进行排序,将无序化为有序,可以用主键顺序访问基表,将随机读转化为顺序读,多页数据记录可一次性读入或根据此次的主键范围分次读入,减少IO操作,提高查询效率。

  • 先根据where条件中的辅助索引获取辅助索引与主键的集合,结果集为rest
select key_column, pk_column from tb where key_column = x order by key_column
  1. 将结果集rest放在buffer里面(read_rnd_buffer_size 大小直到buffer满了),然后对结果集rest按照pk_column排序,得到结果集是rest_sort
  2. 利用已经排序过的结果集,访问表中的数据,此时是顺序IO.
select non_key_column fromtb where pk_column in (rest_sort)

在不使用 MRR 时,优化器需要根据二级索引返回的记录来进行”回表”, 这个过程一般会有较多的随机IO

使用MRR时,SQL语句的执行过程是这样的:

通过上述过程,优化器将二级索引随机的 IO 进行排序,转化为主键的有序排列,从而实现了随机 IO 到顺序 IO 的转化,提升性能。

MRR还可以对某些范围查询进行批量的数据查询,提升性能。

在拆分过程中直接过滤掉不符合查询条件的数据。
将某些范围查询拆分为key对,以此来进行批量数据查询。

例如,表t中有(key_part1,key_part2)的联合索引,

对SQL: select * from t where key_part1 >= 1000 and key_part2 < 2000 and key_part2 = 10000;

索引根据key_part1,key_part2的位置关系进行排序。

  • 如果没有MRR 此时查询类型为range。SQL优化器会先将key_part1大于1000且小于2000的数据全都取出,即使这部分数据的key_part2并不等于10000。待取出这些数据后再根据key_part2的条件进行过滤。 这就导致无用的数据被取出来了。 如果符合key_part1大于1000且小于2000的数据中有相当的数据key_part2不符合条件,那么MRR优化可以使这部分不符合条件的数据不需要读取,使性能获得明显提升。
  • 启用MRR优化 优化器会先将查询条件拆分,然后再进行数据查询。 如:将条件拆分为(1000,10000),(1001,10000),……,最后再根据这些拆分出来的条件进行数据查询。

一个关于MRR的简单例子

表salaries中salary列上有一个辅助索引 idx_s
对于SQL: select * from salaries where salary > 10000 and salary < 40000;而言,

  • 未启用MRR时,查询首先要按照辅助索引进行范围查找,然后再通过辅助索引记录后的主键值回表查询整行数据。Extra只有Using index condition。
  • 启用MRR时,查询首先将命中的辅助索引值放入read_end_buffer_size缓冲区,此时缓冲区中的数据是按照辅助索引的顺序排序的。然后将缓冲区中的数据根据rowid(或显式主键)进行排序。最后根据rowid排序的顺序去访问实际的数据文件,此时就是按照主键顺序去顺序的发生IO。Extra也会有Using MRR信息。

配置MRR的相关参数

  • 优化器开关 optimizer_switch 控制是否启用MRR,默认未启用MRR

mrr={on|off}
mrr_cost_based={on|off}
… e.g: set @@optimizer_switch=’mrr=on,mrr_cost_based=off’;
* 开启方式:mrr = on & mrr_cost_based = on/off

mrr_cost_based用来告诉优化器,要不要基于使用 MRR 的成本,考虑使用 MRR 是否值得(cost-based choice),来决定具体的 sql 语句里要不要使用 MRR。 很明显,对于只返回一行数据的查询,是没有必要 MRR 的,而如果你把 mrr_cost_based 设为 off,那优化器就会通通使用 MRR,这在有些情况下是很 stupid 的,所以建议这个配置还是设为 on,毕竟优化器在绝大多数情况下都是正确的。
– mrr=on,mrr_cost_based=off时,强制开启MRR
– mrr=on,mrr_cost_based=on时,优化器会通过CBO算法确定是否开启MRR特性
* 5.6.35中存在bug:由optimizer_switch引起诡异问题
* 参数read_rnd_buffer_size 用来控制键值缓冲区的大小。二级索引扫描到文件的末尾或者缓冲区已满,则使用快速排序对缓冲区中的内容按照主键进行排序。

Original: https://www.cnblogs.com/konggg/p/14695323.html
Author: 孔个个
Title: MySQL特性:MRR,Multi-Range Read,多范围读

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/621102/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 翻译|是否应该在 Kubernetes 上运行数据库?

    数据库如何在 Kubernetes 上运行?如果可以,哪些类型的数据库和数据最适合使用 K8s?让我们一起来看看。 Kubernetes 是用于自动部署、扩展和管理容器化应用程序的…

    数据库 2023年5月24日
    090
  • IntelliJ IDEA 2017 永久注册方法

    首先下载:JetbrainsCrack-2.6.10-release-enc.rar rover12421大神开发的下载好后改一下后缀.jar 然后放入到IDEA安装bin目录 在…

    数据库 2023年6月14日
    075
  • 关于看源码的心得体会

    前段时间面试,经常遇到面试官在结束的时候问我看过什么开源源码?然后网上对于看源码这块的说法也有各种不同的意见,我进行了总结如下: 不看源码说法: 平常的工作需求、业务忙的一批,哪有…

    数据库 2023年6月6日
    0272
  • 【MySQL】MySQL的安装、卸载、配置、登陆和退出

    1 MySQL安装 安装环境:Win10 64位软件版本:MySQL 5.7.24 解压版 1.1 下载 https://downloads.mysql.com/archives/…

    数据库 2023年5月24日
    093
  • Redis-切片集群

    扩容的思路 纵向扩展 scale up: 一台8G的变成一台24G的 👍 简单 👎 受硬件条件的限制 👎 单机容量大对性能的影响,如Redis的fork操作耗时是和内存数据量正相关…

    数据库 2023年6月11日
    075
  • MySQL之自关联查询

    假设要设计两张表,一张省份表(provinces),一张城市表(citys) 省份表结构 id ptitle 城市表结构 id ctitle proid(表示城市所属的省,对应着省…

    数据库 2023年5月24日
    0131
  • gauss杀进程

    1)查询当前所有连接的状态 select datname,pid,application_name,state from pg_stat_activity; 2)关闭当前state…

    数据库 2023年6月16日
    094
  • 初识HTML5

    HTML5的学习笔记(随便总结,个人使用) 一、认识HTML5的基本格式 1、 标记 标记位于文档的最前端,用于向浏览器说明当前文档使用的是那种HTML标准规范。只有在开头处使用 …

    数据库 2023年6月11日
    081
  • 2010最危险的编程错误(转)

    网络无处不在的今天,安全问题日益严峻,攻击事件层出不穷,应该说,软件系统中代码存在安全漏洞是主要的祸因之一。而这实际上反映了软件开发人员在编程的安全性方面缺乏必要的培训和常识。 由…

    数据库 2023年6月11日
    0101
  • 那些技术实战中的架构设计方法

    上个月我写的一篇文章《关于技术能力的思考和总结》引起了大家的关注,好多读者的评论”以写代想、以想促真、以讲验真”,大家的感受很深刻,基于上次的文章,这篇文章…

    数据库 2023年6月14日
    083
  • Spring框架完整学习!!!

    1.Spring 1.1、简介 1.2、优点 1.3、组成 1.4、拓展 2.IOC思想解析 2.1、场景模拟 2.2、概念解析 2.3、总结 3.初涉Spring 3.1、 基础…

    数据库 2023年6月16日
    092
  • 测试左移和测试右移,我们为何要“上下求索”?

    转载请注明出处❤️ 作者:测试蔡坨坨 原文链接:caituotuo.top/7b9ad46d.html 你好,我是测试蔡坨坨。 今天,我们来聊一聊测试左移和测试右移。 传统测试流程…

    数据库 2023年6月11日
    087
  • springboot~HandlerFunction和RouterFunction

    HandlerFunction和RouterFunction RouterFunction为我们应用程序添加一个新的路由,这个路由需要绑定一个HandlerFunction,做为它…

    数据库 2023年6月6日
    077
  • 你真的懂Python命名吗?

    转载请注明出处❤️ 作者:测试蔡坨坨 原文链接:caituotuo.top/7417a7f0.html 大家好,我是测试蔡坨坨。 今天,我们来聊一下Python命名那些事儿。 名为…

    数据库 2023年6月11日
    0149
  • 23种设计模式之备忘录模式

    文章目录 概述 备忘录模式的优缺点 备忘录模式的结构和实现 * 模式结构 模式实现 总结 概述 备忘录模式(Memento Pattern) 保存一个对象的某个状态,以便在适当的时…

    数据库 2023年6月6日
    089
  • Python–module–OS

    csharp;gutter:true; import os a = os.getcwd() # 获取当前的操作目录 b = os.chdir("C:\Users&quot…

    数据库 2023年6月9日
    092
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球