zoukankan      html  css  js  c++  java
  • mysql 之 MRR

    Multi-Range Read (MRR)

    MRR 的全称是 Multi-Range Read Optimization,是优化器将随机 IO 转化为顺序 IO 以降低查询过程中 IO 开销的一种手段。

    MRR原理

    select non_key_column from tb where ey_column=x;

    在没有使用MRR特性时,MySQL执行查询的伪代码

    第一步 先根据where条件中的辅助索引获取辅助索引与主键的集合,结果集为rest。

    select key_column, pk_column from tb where key_column=x order by key_column

    第二步 通过第一步获取的主键来获取对应的值。

    for each pk_column value in rest do:

    select non_key_column from tb where pk_column=val

    使用MRR特性时,MySQL执行查询的伪代码

    第一步 先根据where条件中的辅助索引获取辅助索引与主键的集合,结果集为rest

    select key_column, pk_column from tb where key_column = x order by key_column

    第二步 将结果集rest放在buffer里面(read_rnd_buffer_size 大小直到buffer满了),然后对结果集rest按照pk_column排序,得到结果集是rest_sort

    第三步 利用已经排序过的结果集,访问表中的数据,此时是顺序IO.

           select non_key_column fromtb where pk_column in (rest_sort)

    综上

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

    1)   优化器将二级索引查询到的记录放到一块缓冲区中

    2)   如果二级索引扫描到文件的末尾或者缓冲区已满,则使用快速排序对缓冲区中的内容按照主键进行排序

    3)   用户线程调用MRR接口取cluster index,然后根据cluster index 取行数据

    4)   当根据缓冲区中的 cluster index取完数据,则继续调用过程 2) 3),直至扫描结束

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

    此外MRR还可以将某些范围查询,拆分为键值对,来进行批量的数据查询,如下:

    SELECT * FROM tWHERE key_part1 >= 1000 AND key_part1 < 2000AND key_part2 = 10000;

    表t上有二级索引(key_part1, key_part2),索引根据key_part1,key_part2的顺序排序。

    若不使用MRR:索引扫描会将key_part1在1000到2000的索引元组,而不管key_part2的值,这样对key_part2不等于10000的索引元组也做了额外的扫描。此时扫描的范围是:

    [{1000, 10000}, {2000, MIN_INT}]此间隔可能包含key_part2不等于10000的部分

    若使用MRR:扫描则分为多个范围,对于每一个Key_part1(1000,1001…,1999)单个值的扫描只需要扫描索引中key_part2为10000的元组。如果索引中包含很多key_part2不为10000的元组,最终MRR的效果越好。MRR扫描的范围是多个单点间隔[{1000, 10000}], ..., [{1999, 10000}] 此间隔只包含key_part2=10000的部分。

    MRR标识

    当使用ICP优化时,执行计划的Extra列显示Using MRR提示

    相关参数

    用optimizer_switch 的标记来控制是否使用MRR.设置mrr=on时,表示启用MRR优化。

    mrr_cost_based表示是否通过cost base的方式来启用MRR.

    当mrr=on,mrr_cost_based=on,则表示cost base的方式还选择启用MRR优化,当发现优化后的代价过高时就会不使用该项优化

    当mrr=on,mrr_cost_based=off,则表示总是开启MRR优化

    SET  @@optimizer_switch='mrr=on,mrr_cost_based=on';

    参数read_rnd_buffer_size 用来控制键值缓冲区的大小。二级索引扫描到文件的末尾或者缓冲区已满,则使用快速排序对缓冲区中的内容按照主键进行排序

    适用场景

    #辅助索引key_part1,查询key_part1在1000到2000范围内的数据

    SELECT * FROM t WHERE key_part1 >= 1000 AND key_part1 < 2000

    不使用MRR:先通过二级索引的key_part1字段取出满足条件的key_part1,pk_col order by key_part1.然后通过pk_col去表中取出满足条件的数据,此时,因为取出的pk_col是乱序的,而表又是pk_col存放数据的,当去表中取数据时,则会产生大量的随机IO

    使用MRR:先通过二级索引的key_part1字段取出满足条件的key_part1,pk_col order by key_part1.放到缓存中(read_rnd_buffer_size),当对应的缓冲满了以后,将这部分key值按照pk_col排序,最后再按照排序后的reset去取表中数据,此时pk_col1是顺序的,将随机IO转化为顺序IO,多页数据记录可一次性读入或根据此次的主键范围分次读入,以减少IO操作,提高查询效率

    使用限制

    MRR 适用于range、ref、eq_ref的查询

  • 相关阅读:
    一个优秀测试的自我修养
    二.自动化接口测试---用例设计思路、模版
    关于文件读写的一些笔记
    模块导入---如何在一个文件中导入其它模块,来调用它的变量、函数等,以节省代码量
    变量以及作用域----(局部变量、全部变量...)
    python连接mysql数据库
    python修改txt文件内容
    使用PyQt4写界面后台程序方法总结
    unresolved import 解决办法
    怎样使用pyinstaller打包
  • 原文地址:https://www.cnblogs.com/hansc-blog/p/9685139.html
Copyright © 2011-2022 走看看