【MySQL】MySQL性能优化之Block Nested-Loop Join(BNL)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 一 介绍  相信许多开发/DBA在使用MySQL的过程中,对于MySQL处理多表关联的方式或者说性能一直不太满意。对于开发提交的含有join的查询,一般比较抗拒,从而建议将join拆分,避免join可能带来的性能问题,同时也增加了程序和DB的网络交互。
一 介绍
  相信许多开发/DBA在使用MySQL的过程中,对于MySQL处理多表关联的方式或者说性能一直不太满意。对于开发提交的含有join的查询,一般比较抗拒,从而建议将join拆分,避免join可能带来的性能问题,同时也增加了程序和DB的网络交互。
5.5 版本之前,MySQL本身只支持一种表间关联方式,就是嵌套循环(Nested Loop)。如果关联表的数据量很大,则join关联的执行时间会非常长。在5.5以后的版本中,MySQL通过引入BNL算法来优化嵌套执行,本文介绍两种join算法 Nested-Loop Join (NLJ) 和Block Nested-Loop Join(BNL) .


二 原理
2.1 Nested Loop Join算法
  NLJ 算法:将驱动表/外部表的结果集作为循环基础数据,然后循环从该结果集每次一条获取数据作为下一个表的过滤条件查询数据,然后合并结果。如果有多表join,则将前面的表的结果集作为循环数据,取到每行再到联接的下一个表中循环匹配,获取结果集返回给客户端。
Nested-Loop 的伪算法如下:
  1. for each row in t1 matching range {
  2.   for each row in t2 matching reference key {
  3.      for each row in t3 {
  4.       if row satisfies join conditions,
  5.       send to client
  6.     }
  7.   }
  8.  }
  因为普通Nested-Loop一次只将一行传入内层循环, 所以外层循环(的结果集)有多少行, 内存循环便要执行多少次.在内部表的连接上有索引的情况下,其扫描成本为O(Rn),若没有索引,则扫描成本为O(Rn*Sn)。如果内部表S有很多记录,则SimpleNested-Loops Join会扫描内部表很多次,执行效率非常差。

2.2 Block Nested-Loop Join算法 
 
BNL 算法:将外层循环的行/结果集存入join buffer, 内层循环的每一行与整个buffer中的记录做比较,从而减少内层循环的次数.
举例来说,外层循环的 结果集是100行,使用NLJ 算法需要扫描内部表100次,如果使用BNL算法,先把对Outer Loop表(外部表)每次读取的10行记录放到join buffer,然后在InnerLoop表(内部表)中直接匹配这10行数据,内存循环就可以一次与这10行进行比较, 这样只需要比较10次,对内部表的扫描减少了9/10。所以BNL算法就能够显著减少内层循环表扫描的次数.
前面描述的query, 如果使用join buffer, 那么实际join示意如下:
  1. for each row in t1 matching range {
  2.    for each row in t2 matching reference key {
  3.     store used columns from t1, t2 in join buffer
  4.     if buffer is full {
  5.       for each row in t3 {
  6.          for each t1, t2 combination in join buffer {
  7.           if row satisfies join conditions,
  8.           send to client
  9.         }
  10.        }
  11.       empty buffer
  12.     }
  13.   }
  14. }


  15. if buffer is not empty {
  16.    for each row in t3 {
  17.     for each t1, t2 combination in join buffer {
  18.       if row satisfies join conditions,
  19.       send to client
  20.      }
  21.   }
  22. }
如果t1, t2参与join的列长度只和为s, c为二者组合数, 那么t3表被扫描的次数为 
  1. (S * C)/join_buffer_size + 1
扫描t3的次数 随着join_buffer_size的增大而减少 , 直到join buffer能够容纳所有的t1, t2组合,  再增大join buffer size, query 的速度就不会再变快了.

2.3  MySQL使用Join Buffer有以下要点:
   1. join_buffer_size变量决定buffer大小。
  2. 只有在join类型为all, index, range的时候才可以使用join buffer。
  3. 能够被buffer的每一个join都会分配一个buffer, 也就是说一个query最终可能会使用多个join buffer。
  4. 第一个nonconst table不会分配join buffer, 即便其扫描类型是all或者index。
  5. 在join之前就会分配join buffer, 在query执行完毕即释放。
  6. join buffer中只会保存参与join的列, 并非整个数据行。

三  如何使用 
  5.6版本及以后,优化器管理参数optimizer_switch中中的block_nested_loop参数控制着BNL是否被用于优化器。默认条件下是开启,若果设置为off,优化器在选择 join方式的时候会选择NLJ算法。

四 参考资料
 
     5.6 版本BNL 支持 outer join and semi-join ,并且和其他的特性比如BKA 相关联,后面会写文章整理其他的优化点。
    Nested-Loop Join Algorithms
    《 Block Nested-Loop and Batched Key Access Joins
    mysql的join buffer

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
12月前
|
SQL 分布式计算 运维
2023云数据库技术沙龙|ByteHouse云数仓版查询性能优化和MySQL生态完善
在2023云数据库技术沙龙 “MySQL x ClickHouse” 专场上,火山引擎ByteHouse的研发工程师游致远,为大家分享一下《ByteHouse云数仓版查询优化和MySQL生态完善》的一些工作。
162 0
|
关系型数据库 MySQL 测试技术
增补mysql的性能优化数条经验
增补mysql的性能优化数条经验
85 0
|
分布式计算 算法 大数据
调度、模型、同步与任务——阿里云大数据数仓建设性能优化方案
对于阿里云大数据数仓建设性能优化而言,主要可以从调度优化、模型优化、同步优化以及任务优化这四个方面着手。其实,对于性能优化而言,最终还是会归结到“资源”之上,所以资源是否足够,分配是否合理也是我们在进行性能优化时必须考虑的关键所在。
4269 1
|
SQL 关系型数据库 MySQL
|
SQL 监控 关系型数据库
|
算法 搜索推荐 关系型数据库
|
算法 搜索推荐 关系型数据库
【MySQL】性能优化之 order by (一)
前言    工作过程中,各种业务需求在访问数据库的时候要求有order by排序。有时候不必要的或者不合理的排序操作很可能导致数据库系统崩溃。如何处理好order by排序呢?本文从原理以及优化层面介绍 order by 。
1007 0