MySQL中Nested-Loop Join算法小结

 更新时间:2015年12月10日 11:37:33   投稿:hebedich  
数据库中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用户和数据权限管理详解

    MySQL用户和数据权限管理详解

    这篇文章主要为大家详细介绍了MySQL数据库管理中的用户和数据权限管理,文中的示例代码讲解详细,对我们学习MySQL有一定帮助,需要的可以参考一下
    2022-08-08
  • 简述MySql四种事务隔离级别

    简述MySql四种事务隔离级别

    这篇文章主要介绍了MySql四种隔离级别,帮助大家更好的理解和学习MySQL,感兴趣的朋友可以了解下
    2020-08-08
  • Mysql5.7.17 winx64.zip解压缩版安装配置图文教程

    Mysql5.7.17 winx64.zip解压缩版安装配置图文教程

    这篇文章主要介绍了Mysql5.7.17 winx64.zip解压缩版安装配置图文教程,需要的朋友可以参考下
    2018-03-03
  • MySQL多实例配置方案

    MySQL多实例配置方案

    MySQL多实例就是,在一台机器上开启多个不同的服务端口(如:3306,3307,3308...),运行多个MySQL服务进程,这些服务进程通过不同的socket监听不同的端口提供服务。
    2018-04-04
  • mysql如何比对两个数据库表结构的方法

    mysql如何比对两个数据库表结构的方法

    这篇文章主要介绍了mysql如何比对两个数据库表结构的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • MySQL如何匹配字符串函数

    MySQL如何匹配字符串函数

    MySQL提供多个字符串匹配函数,如like、locate、position、instr和find_in_set,其中locate、position、instr和find_in_set均返回字符在字段中的索引(如果包含),否则返回0,特别地,find_in_set适用于字段为数组的情况
    2024-11-11
  • MySQL中字符串函数详细介绍

    MySQL中字符串函数详细介绍

    通常以串的整体作为操作对象,如:在串中查找某个子串、求取一个子串、在串的某个位置上插入一个子串以及删除一个子串等。
    2011-05-05
  • mysql中limit查询踩坑实战记录

    mysql中limit查询踩坑实战记录

    在MySQL中我们常常用order by来进行排序,使用limit来进行分页,下面这篇文章主要给大家介绍了关于mysql中limit查询踩坑的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • MySQL基础入门之Case语句用法实例

    MySQL基础入门之Case语句用法实例

    case语句是mysql中的一个条件语句,可以在字段中使用case语句进行复杂的筛选以及构造新的字段,下面这篇文章主要给大家介绍了关于MySQL基础入门之Case语句用法的相关资料,需要的朋友可以参考下
    2022-08-08
  • LInux下安装MySQL5.6 X64版本步骤详解

    LInux下安装MySQL5.6 X64版本步骤详解

    这篇文章主要介绍了LInux下安装MySQL5.6 X64版本步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04

最新评论