Mysql优化算法-MRR(Multi-Range Read Optimization)

一、优化器索引算法查询

官网文档:https://dev.mysql.com/doc/refman/5.7/en/optimization.html

优化器参数参考:https://dev.mysql.com/doc/refman/5.7/en/switchable-optimizations.html

select @@optimizer_switch;
index_merge=on,
index_merge_union=on,
index_merge_sort_union=on,
index_merge_intersection=on,
engine_condition_pushdown=on,
index_condition_pushdown=on,
mrr=on, mrr_cost_based=on,
block_nested_loop=on,
batched_key_access=off,
materialization=on,
semijoin=on,
loosescan=on,
firstmatch=on,
duplicateweedout=on,
subquery_materialization_cost_based=on,
use_index_extensions=on,
condition_fanout_filter=on,
derived_merge=on

二、MRR优化

当表很大且没有存储在存储引擎的缓存中时,在辅助索引上使用范围扫描读取行可能会导致对基本表的许多随机磁盘访问。

通过磁盘扫描多范围读取(MRR)优化,MySQL尝试通过只扫描索引并收集相关行的键来减少范围扫描的随机磁盘访问次数。然后对键进行排序,最后使用主键的顺序从基表检索行

磁盘扫描MRR的动机是减少随机磁盘访问的数量,而实现对基本表数据的更连续的扫描。

多范围读取优化提供了以下好处:

  • MRR允许基于索引元组按顺序而不是随机顺序访问数据行。服务器获取一组满足查询条件的索引元组,根据数据行ID的顺序对它们进行排序,并使用排序后的元组按顺序检索数据行。这使得数据访问效率更高,成本更低。
  • MRR允许对需要通过索引元组访问数据行的操作的键访问请求进行批处理,例如范围索引扫描和使用连接属性索引的等价连接。MRR在一系列索引范围上迭代以获得合格的索引元组。随着这些结果的积累,它们被用于访问相应的数据行。在开始读取数据行之前,不需要获取所有的索引元组。

虚拟生成的列上创建二级索引不支持MRR优化。InnoDB支持在虚拟生成的列(参考官方文档:https://dev.mysql.com/blog-archive/generated-columns-in-mysql-5-7-5/)上建立二级索引。

以下场景说明了MRR优化在哪些情况下具有优势:

  • 场景A: MRR可以用于InnoDB和MyISAM表的索引范围扫描和等价连接操作。

    1. 索引元组的一部分在缓冲区中累积。
    2. 缓冲区中的元组按其数据行ID排序。
    3. 根据排序后的索引元组序列访问数据行。
  • 场景B: MRR可以用于NDB表的多范围索引扫描,或者通过属性执行等价连接。

    1. 一部分范围(可能是单键范围)积累在提交查询的中心节点上的缓冲区中。
    2. 这些范围被发送到访问数据行的执行节点。
    3. 被访问的行被打包到包中并发送回中心节点。
    4. 带数据行的接收包被放置在一个缓冲区中。
    5. 从缓冲区读取数据行。

当使用MRR时,EXPLAIN输出中的Extra列显示Using MRR。

如果不需要访问全表行来产生查询结果,InnoDB和MyISAM不使用MRR。在这种情况下,如果结果完全基于索引元组中的信息(通过覆盖索引)产生,MRR没有带来任何好处。

optimizer_switch系统变量中两个标志提供了一个使用MRR优化的接口。mrr标志控制MRR是否可以使用。如果mrr被启用(开启),mrr_cost_based标志控制优化器是否尝试在使用或不使用MRR(开启)或尽可能使用MRR(关闭)之间做出基于成本的选择。缺省情况下,mrr为on, mrr_cost_based为on.

更多优化器参数参考:https://dev.mysql.com/doc/refman/5.7/en/switchable-optimizations.html

你可能感兴趣的:(sql,mysql,数据库)