zoukankan      html  css  js  c++  java
  • MySQL 5.6 优化点(MRR、BKA 与 ICP)

    最近在学习 MySQL 相关的东西,大致整理一下

    MRR —— Multi-Range Read Optimization

    MRR 是优化器将随机 IO 转化为顺序 IO,以降低 IO 开销的手段。

    二级索引中存储的是索引列和主键值,当查询列不都存在与索引列中时(即不是覆盖索引的情况),需要回表操作。然而回表获取完整用户记录可能回产生随机 IO(当数据量较多且比较分散时,随机 IO 性能较低,后会单写一篇「表空间」的笔记),为减少这种随机 IO,MySQL 首先只在二级索引中查询,统计关联行的主键,然后根据主键值排序, 最后从聚簇索引中按照主键排序获取完整记录。

    使用 MRR 时的查询过程:

    1. 优化器将从二级索引中查询到的记录放到缓冲区中;
    2. 如果缓冲区已满,或者扫描到二级索引文件末尾,使用快排对缓冲区的数据按照主键排序;
    3. 用户线程根据缓冲区的内容,从聚簇索引中获取数据;
    4. 当缓冲区内容读取完毕时,重复上述过程,直到扫描结束

    如何查看一条 SQL 是不是 MRR 呢?我们 EXPLAIN 执行一条 SQL 时,使用 MRR 的查询会在 Extra 列出现 Using MRR 关键字。

    optimizer_switch 变量控制是否开启 MRR,默认是开启的,关闭的话 set optimizer_switch = 'mrr=off'

    ICP —— Index Condition Pushdown Optimization(索引下推)

    2020-01-18 更新索引下推的分析,添加 Index Key、Index Filter 与 Table Filter。

    这个就比较常见了,MySQL 分层架构中最上面是负责管理连接的,第二层是 Server 层用来语法解析、查询优化的,最后一层是存储引擎层来和文件系统打交道的。

    强烈推荐阅读何登成大佬 where 条件在数据库中提取与应用浅析 这篇文章,where 条件可以分为三大类,分别是 Index Key(First Key、Last Key)、Index Filter 以及 Table Filter。

    Index Key

    用于确认索引查询范围,既然是范围肯定有开头有结束,分别对应 Index First Key 与 Index Last Key。

    Index First Key 的提取从索引第一列开始,依次对全部索引列进行如下判断,判断 where 条件中是否有针对该列的 >=、= 条件,如果有就将该条件加到 Index First Key 中,并查找下一个索引列;where 条件如果有针对该列的 > 条件,同样将该条件添加到 Index First Key 中并终止 Index First Key 的提取。

    Index Last Key 的提取与上面 First Key 类似,只是变成了 <。仍旧从索引第一列开始,判断 where 条件是否有针对该列的 <=、= 条件,如果有就将该条件添加到 Index Last Key 中,并查找下一个索引列;where 条件中如果有针对该列的 < 条件,同样将该条件加到 Index Last Key 中并终止 Index Last Key 的提取。

    Index Filter

    通过对 Index Key 的提取,我们从二级索引对应的 B+ 树中确认了二级索引的扫描范围,但并不代表该范围内的每一项都满足查询条件(这里说的是二级索引包含的列)。何大佬写的 Index Filter 查询过程看了好多遍,实在没看明白,贴图过来以后看。

    在这里插入图片描述
    Index First Key 用来确认索引的起始范围,只进行一次判断,从 B+ 树根节点开始往下遍历,直到找到正确的叶节点位置(并定位其中的索引项)。Index Last Key 则是用来定位索引的终止范围,对确定了起始范围之后读取到的每个索引记录,均需要判断是否超过了 Index Last Key 的范围(超过了就结束索引列的查询),同时还要与 Index Filter 对比(不满足 Index Filter 条件就丢弃,继续读取下一条记录)。

    Table Filter

    所有在索引列中不存在的查询条件,均属于 Table Filter。既然这个查询条件在索引列中不存在,肯定需要回表查询,何大佬写的太经典了,直接抄过来了。

    Table Filte 是最后一道 where 条件的防线,用于过滤通过前面索引的层层考验的记录,此时的记录已经满足了 Index First Key 与 Index Last Key 构成的范围,并且满足 Index Filter 的条件,回表读取了完整的记录,判断完整记录是否满足 Table Filter 中的查询条件,同样的,若不满足,跳过当前记录,继续读取索引的下一条记录,若满足,则返回记录,此记录满足了 where 的所有条件,可以返回给前端用户。

    MySQL 5.6 之前不区分 Index Filter 还是 Table Filter,存储引擎层找到满足 Index Key 的所有二级索引记录后,都会回表取完整记录,然后由 Server 层来对 WHERE 条件做过滤。有 ICP 后,Index Filter 这部分就交给存储引擎层去做了。

    这么做的优点呢?一是减少了回表的开销,二是减少了存储引擎层返回 Server 层的时间。

    ICP 支持 InnoDB 和 MyISAM 引擎,对于 InnoDB ICP 只支持二级索引,不支持聚簇索引,因为聚簇索引的全部数据都从 InnoDB Buffer 中读取,不涉及磁盘 IO。在二级索引是复合索引且前面的条件过滤性较低的情况下,打开 ICP 可以有效的降低 Server 层和 Engine 层之间交互的次数,从而有效的降低在运行时间。

    The goal of ICP is to reduce the number of full-row reads and thereby reduce I/O operations. For InnoDB clustered indexes, the complete record is already read into the InnoDB buffer. Using ICP in this case does not reduce I/O.

    ICP 也有一些限制条件:

    1. 不适用于子查询、不支持主键索引
    2. ICP的优化策略可用于range、ref、eq_ref、ref_or_null 类型的访问数据方法

    EXPLAIN 时,使用 ICP 的查询会在 Extra 列出现 Using index condition 关键字。

    Reference

  • 相关阅读:
    按钮,文本框
    d01
    第一天,对于课程和工作的了解
    javaweb概念性知识
    Jdbc概念性知识
    连接数据库,和数据增删改
    oracle基础概念性知识
    面向对象java知识汇总题
    javaweb
    date日期
  • 原文地址:https://www.cnblogs.com/Zhoust/p/14994593.html
Copyright © 2011-2022 走看看