数据库中JOIN操作的实现主要有三种:嵌套循环连接(Nested Loop Join),归并连接(Merge Join)和散列连接或者哈稀连接(Hash Join)。其中嵌套循环连接又视情况又有两种变形:块嵌套循环连接和索引嵌套循环连接。

不知不觉的玩了两年多的MySQL,发现很多人都说MySQL对比Oracle来说,优化器做的比较差,其实某种程度上来说确实是这样,但是毕竟MySQL才到5.7版本,Oracle都已经发展到12c了,今天我就看了看MySQL的连接算法,嗯,现在来说还是不支持Hash Join,只有Nested-Loop Join,那今天就总结一下我学习的心得吧。

Nested-Loop Join基本算法实现,伪代码是这样:

for each row in t1 matching range {

for each row in t2 matching reference key {

for each row in t3 {

if row satisfies join conditions,

send to client

}

}

}

这段代码很简单,虽然我也不怎么会写代码,但是我还是看得懂的。这里假设有三张表,t1, t2, t3,这段代码,分别会展现出explain计划里的range, ref和ALL,表现在SQL执行计划层里,t3就会进行一次全表扫描,我今天在这个地方看到了一个很妖的优化SQL方法,Straight-join:http://hidba.ga/2014/09/26/join-query-in-mysql/,其中提到了驱动表的概念,那么对应过来,驱动表就是伪代码里的t3表,博文里说MySQL会自动选择结果集最小的表作为驱动表,作为算法分析,这样选择驱动表确实是消耗最小的办法。那么这里还提到了,通过缩小驱动表结果集进行连接优化,那么根据这个算法来看,结果集较小的驱动表确实可以使循环次数减少。

当然了,MySQL自己在这个算法基础上,演进出了Block Nested-Loop join算法,其实基本上和上面的算法没有区别,伪代码如下:

for each row in t1 matching range {

for each row in t2 matching reference key {

store used columns from t1, t2 in join buffer

if buffer is full {

for each row in t3 {

for each t1, t2 combination in join buffer {

if row satisfies join conditions,

send to client

}

}

empty buffer

}

}

}

if buffer is not empty {

for each row in t3 {

for each t1, t2 combination in join buffer {

if row satisfies join conditions,

send to client

}

}

}

这个算法,将外层循环的数据缓存在join buffer中,内层循环中的表回合buffer中的数据进行对比,从而减少循环次数,这样便可以提高效率。官网上有个example,我有点没有看明白:如果有10行被缓存到了buffer里,这10行被传给了内层循环,内层循环的所有行都会和buffer中的这10行进行对比。原文是这样的:

For example, if 10 rows are read into a buffer and the buffer is passed to the next inner loop, each row read in the inner loop can be compared against all 10 rows in the buffer

如果S指的是t1, t2组合在缓存中的大小,C是这些组合在buffer中的数量,那么t3表被扫描的次数应该是:

(S * C)/join_buffer_size + 1

根据这个算式,join_buffer_size越大,扫描的次数越小,如果join_buffer_size到了能缓存所有之前的行组合,那么这时就是性能最好的时候,之后再增大也就没有什么效果了。

在有索引的情况下,MySQL会尝试去使用Index Nested-Loop Join算法,在有些情况下,可能Join的列就是没有索引,那么这时MySQL的选择绝对不会是最先介绍的Simple Nested-Loop Join算法,因为那个算法太粗暴,不忍直视。数据量大些的复杂SQL估计几年都可能跑不出结果,如果你不信,那就是too young too simple。或者Inside君可以给你些SQL跑跑看。

Simple Nested-Loop Join算法的缺点在于其对于内表的扫描次数太多,从而导致扫描的记录太过庞大。Block Nested-Loop Join算法较Simple Nested-Loop Join的改进就在于可以减少内表的扫描次数,甚至可以和Hash Join算法一样,仅需扫描内表一次。

mysql loop嵌套_MySQL中Nested-Loop Join算法小结相关推荐

  1. mysql的一个bug Block Nested Loop

    2019独角兽企业重金招聘Python工程师标准>>> 版本 5.7.20-19-log mysql 官网bug https://bugs.mysql.com/bug.php?id= ...

  2. mysql right关键字_MYSQL 中的LEFT( RIGHT ) JOIN使用ON 与WHERE 筛选的差异

    有这样的一个问题:查询使用mysql中left(right)join筛选条件在on与where查询出的数据是否有差异. 可能只看着两个关键字看不出任何的问题.那我们使用实际的例子来说到底有没有差异. ...

  3. mysql intersect用法格式_MySQL中使用INNER JOIN来实现Intersect并集操作

    MySQL中使用INNER JOIN来实现Intersect并集操作 一.业务背景 我们有张表设计例如以下: CREATE TABLE `user_defined_value` ( `RESOURCE ...

  4. mysql explain 索引_MySql中Explain详解与索引最佳实践

    使用EXPLAIN关键字可以模拟优化器执行SQL语句,从而知道MySQL是 如何处理你的SQL语句的.分析你的查询语句或是结构的性能瓶颈 下面是使用 explain 的例子: 在 select 语句之 ...

  5. mysql 全连接_MySQL全连接(Full Join)实现,union和union all用法

    MySQL本身不支持你所说的full join(全连接),但可以通过union来实现 , 下面是一个简单测试,可以看看: mysql> CREATE TABLE a(id int,name ch ...

  6. explain mysql怎么用_mysql中explain用法详解

    EXPLAIN用于SELECT语句中的每个表返回一行信息.表以它们在处理查询过程中将被MySQL读入的顺序被列出 如果在select语句前放上关键词explain,mysql将解释它如何处理selec ...

  7. mysql提取数字_Mysql中实现提取字符串中的数字的自定义函数分享

    因需要在mysql的数据表中某一字符串中的字段提取出数字,在网上找了一通,终于找到了一个可用的mysql函数,可以有效的从字符串中提取出数字. 该mysql提取出字符串中的数字函数如下: 复制代码 代 ...

  8. mysql 关联索引_mysql中关于关联索引的问题——对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引?...

    情况描述:在MySQL的user表中,对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引? 根据查询字段的位置不同来决定,如查询a,     a,b    a,b, ...

  9. mysql range用法_MySQL中Explain的用法总结(详细)

    本篇文章给大家带来的内容是关于MySQL中Explain的用法总结(详细),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 执行计划(query Execution plan) 语法e ...

最新文章

  1. extern与头文件(*.h)的区别和联系
  2. 【系统分析与设计】UML协作图绘制方法(真の能看懂~!)
  3. VS2015编译MuPDF 1.13.0源码(详细)
  4. RuntimeError: Failed to register operator torchvision::_new_empty_tensor_op. +torchtorchversion版本匹配
  5. #前端# 解决前端页面滑动不顺畅的问题
  6. 资源放送丨《MySQL的查询与优化》PPT视频
  7. UnityEngine.UI.dll is in timestamps but is not known in assetdatabase
  8. DropDownList操作;ListBox操作;动态创建控件;Response.Write(欢迎学习ASP.NET''!);
  9. vue导出服务器上的excel文件,详解如何在Vue项目中导出Excel
  10. 《等一朵花开》读书感悟
  11. 高德地图基本开发流程
  12. mac 重置 android手机系统,Mac OS X下Android系统华为手机无法连接问题之解决方案
  13. Image类--旋转和翻转图片
  14. Android热修复之Tinker集成最新详解
  15. matlab中如何用数组绘图,matlab 基础学习(1)——数组,矩阵操作和绘图基础学习...
  16. GS108E+GS105E+TP-LINK TL-WDR5620实现联通家庭宽带IPTV单线复用教程
  17. 实战 | 电信客户流失分析与预测
  18. mysql面向用户是什么意思_原来大厂的MySQL面试会问这些问题!
  19. 编程从C语言的梅花5开始
  20. 谷歌翻译下载-免费谷歌翻译软件下载

热门文章

  1. tensor和模型 保存与加载 PyTorch
  2. pandas以前笔记
  3. GPU上稀疏矩阵的基本线性代数
  4. 激光雷达和V2X技术
  5. CVPR目标检测与实例分割算法解析:FCOS(2019),Mask R-CNN(2019),PolarMask(2020)
  6. 2021年大数据Kafka(九):kafka消息存储及查询机制原理
  7. 【CV】Anaconda 安装教程|CSDN创作打卡
  8. Ubuntu安装MongoDB
  9. win10+Linux双系统安装及一些配置问题
  10. pyhton re模块