在阿里巴巴的java开发手册有这么一条强制规定:超过三个表禁止join,需要join的字段,数据类型保持绝对一致,多表关联查询时,要保证被关联的字段需要有索引。

为什么尽量避免使用join?如果使用join,我们应该怎么用呢?接下来我们就一起聊一聊关于join的几种算法。

Simple Nested-Loop Join

Simple Nested-Loop Join算法是指读取驱动表t1中的每行数据,将每行数据传递到被驱动表t2上,取出被驱动表t2中满足条件的行,和t1组成结果集。

在这个算法中,需要对t1进行全表扫描,假设t1表1000行数据,那么需要对t2表进行1000次全表扫描,假设t2表也是1000行数据,那么就需要扫描1000 X 1000=1000000行。

示例图如下:当t1表5行数据,t2表5行数据时,需要扫描25行数据。

Index Nested-Loop Join

index nested-loop join算法的优化思路是通过驱动表的匹配条件,直接与被驱动表的索引进行匹配,减少了被驱动表的扫描次数。

该算法同样要对驱动表t1进行全表扫描,但是我们在拿着t1表的数据去被驱动表t2进行匹配时可以利用t2表的索引,如果t1表中1000行数据,t2表中1000行数据,那么一共就需要扫描1000+1000=2000行数据。这个过程就跟我们写程序时的嵌套查询类似,并且可以用上被驱动表的索引,所以称之为“Index Nested-Loop Join”,简称 NLJ。

示例如下:当t1表有5行数据,t2表有5行数据时,一共需要扫描5+5=10行数据。

Block Nested-Loop Join

Block Nested-Loop join,基于块的嵌套循环,简称BNL算法,其优化思路主要是减少被驱动表的循坏次数,它会将驱动表的数据缓存起来,把参与查询的列缓存到join buffer里,然后拿join buffer里的数据批量与内层表的数据在join buffer中进行匹配,满足join条件的,作为结果集的一部分返回。

可以看到该算法对两个表都进行了全表扫描,因此扫描的行数是两个表的行数之和。这种场景下,虽然在扫描行数上和NLJ算法一样,但是由于BNL算法是在内存中进行判断,速度上会快很多。

join buffer的大小是由参数join_buffer_size设定,默认256k。如果一次放不下驱动表的所有数据,会分段放,这种情况下会导致被驱动表扫描多次。如果被驱动表是冷数据表,并且多次扫描读取被驱动表间隔超过1S的话,就会将他放入LRU链表的young区域,导致业务数据无法进入热数据区,减少了bufferpool的命中率,这又是另外一个课题了,暂不过多展开。我们可以通过调大join_buffer_size来提高缓存的数据量,减少对被驱动表的扫描次数。

启用BNL算法需要在optimizer_switch参数中设置block_nested_loop=on。

Batched Key Access

BNL算法提升了join的性能,但是它在通过辅助索引连接后需要回表,就会消耗大量的随机I/O,我们知道随机IO对MySQL的影响是非常大的。因此MySQL5.6引入了Batched Key Access(BKA,批量键访问联接)算法。

再说BKA算法时不得不提的就是MySQL的Multi-Range Read 优化,MRR的目的主要是减少磁盘的随机访问。我们都知道,Innodb索引采用的是B+tree的数据结构,数据保存在主键索引中,并且是按照主键递增的顺序插入的,但是二级索引的排列顺序和主键的排列顺序一般是不一样的,它保存的主键值也并非按照主键顺序排列,在回表时就会出现随机访问主键索引的情况。所以如果可以按照主键递增顺序查询的话,对磁盘的读比较接近顺序读,这样就能够提升读性能。

MRR优化的思路就是在进行范围查询时,在得到主键值之后,先按照主键的顺序进行排序,然后拿着排好序的主键ID再去主键索引进行查询,这样就能体现出顺序性的优势了。因为是多值查询,所以一般用于range、ref类型的查询。

再说会BKA算法,当被驱动表上有索引可以利用时,那么就在行提交给被 join 的表之前,先对两个表的对应列的索引字段进行join,得到主键值后,按照主键排好序后,利用 MRR 技术,批量访问表取数据,减少了随机 IO。但是如果被 join 的表没用索引的话,那就只能使用BNL算法了。

具体算法如下图:

开启BKA和MRR的方式:

set optimizer_switch='mrr=on,mrr_cost_based=off,batched_key_access=on';

MySQL在8.0版本已经实现了hash join,这里暂不做介绍。

小结

如何优化join的速度呢,这里给出如下几点建议:

尽量避免使用join。

用小表作为驱动表,减少外层循环的次数。

多表关联查询时,要保证被关联的字段要有索引。

适当增大join_buffer_size的值,缓存的数据越多,就越能减少被驱动表扫描的次数。

减少不必要的字段查询。

需要join的字段,数据类型保持绝对一致。

本文分享自微信公众号 - MySQL数据库技术栈(Mysqltechnology)。

如有侵权,请联系 support@oschina.cn 删除。

本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

mysql join 算法_【MySQL】之join算法详解相关推荐

  1. mysql curd操作_(四):CURD操作详解(增删改查)

    基本操作:增删改查 一.增 增: insert 介绍: mongodb存储(单位)的是文档,. 文档是json格式的对象. 语法: db.collectionName.isnert(document) ...

  2. (转载)MySQL数据库的主键和外键详解

    主键 主键的定义 主键:表中经常有一个列或多列的组合,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可强制表的实体完整性.当创建或更改表时可通过定义 PRIMARY KEY 约束来 ...

  3. mysql安装后目录介绍,MySQL安装后的目录结构及配置文件详解

    MySQL安装后的目录结构及配置文件详解 MySQL安装后的目录结构及配置文件详解 MySQL目录结构说明 MySQL 安装完成后,会在磁盘上生成一个目录,该目录就被称为 MySQL 的安装目录. M ...

  4. 大白话解析Apriori算法python实现(含源代码详解)

    大白话解析Apriori算法python实现(含源代码详解) 一.专业名词解释 二.算法思路 三.python代码实现 四.Aprioir的优点.缺点及改进方法 本文为博主原创文章,转载请注明出处,并 ...

  5. JAVA中希尔排序去的讲解_java 中基本算法之希尔排序的实例详解

    java 中基本算法之希尔排序的实例详解 希尔排序(Shell Sort)是插入排序的一种.也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法.该方法因DL.Shel ...

  6. EM算法(Expectation Maximization Algorithm)详解

    EM算法(Expectation Maximization Algorithm)详解 主要内容 EM算法简介 预备知识  极大似然估计 Jensen不等式 EM算法详解  问题描述 EM算法推导 EM ...

  7. php mysql修改命令_PHP编程:mysql alter table命令修改表结构实例详解

    <PHP编程:mysql alter table命令修改表结构实例详解>要点: 本文介绍了PHP编程:mysql alter table命令修改表结构实例详解,希望对您有用.如果有疑问,可 ...

  8. mysql int(3)与int(11)的区别详解

    这篇文章主要介绍了mysql int(3)与int(11)的区别详解的相关资料,需要的朋友可以参考下 mysql int(3)与int(11)的区别 总结,int(M) zerofill,加上zero ...

  9. [Python从零到壹] 八.数据库之MySQL和Sqlite基础知识及操作万字详解

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  10. mysql gz 安装_Linux下安装mysql 5.7.17.tar.gz的教程详解

    1.创建MySQL组和mysql用户 groupadd mysql useradd -r -g mysql mysql 2.拷贝: cp -R mysql-5.7.16-linux-glibc2.5- ...

最新文章

  1. 操作像素(一)--存取像素值
  2. 洛谷 P1064 金明的预算方案
  3. 【PAT甲级 排序】1096 Consecutive Factors (20 分) C++ 全部AC
  4. GPU下train 模型出现nan
  5. IM即时通讯服务将成联结谷歌、雅虎纽带(图)
  6. 避开10个面试大坑,接offer成功率提升至99%
  7. 华为开源构建工具_5个开源工具可快速构建地图应用
  8. 配置jupyter notebook到conda env虚拟环境里可运行
  9. ctf xss利用_Csrf+Xss组合拳
  10. Storm之——实现井字棋游戏(人工智能)
  11. ONMF正交非负矩阵分解·论文总结
  12. 浅析微信支付:公众平台卡券功能开通、HTML5线上发券(JS-SDK接口)、查看卡券详情
  13. Alpha 冲刺(1/10)
  14. python官网学习爬虫资料_Python爬虫学习?
  15. 实践一:mipsel-栈溢出漏洞_开启telnet服务_反弹shell
  16. SWR:最具潜力的 React Hooks 数据请求库
  17. 教你如何做好微信营销说到微信营销
  18. 英特尔发布Xeon D-1600处理器:10nm工艺 性能提升40%
  19. xinetd使用指南
  20. [翻译]CryEngine3中裁剪剔除解释

热门文章

  1. 条款9:不要在构造和析构过程中调用virtual函数
  2. ARM公布“物联网”嵌入式mbed OS系统软件平台
  3. PostgreSQL在何处处理 sql查询之五十一
  4. 简单的总是好的,在这个复杂的世界: java simple log
  5. 孤岛营救与汽车加油行驶问题
  6. js返回上一页并刷新代码整理
  7. Android应用中的动画详细使用教程
  8. CentOS 6 php5.6.0一键部署脚本
  9. LVM是逻辑盘卷管理1
  10. CCNA Discovery第二学期 (版本 4.1)