《DBNotes:Join算法的前世今生》

目录

  • NestLoopJoin算法
    • Simple Nested-Loop Join
    • Index Nested-Loop Join
    • Block Nested-Loop Join
    • Batched Key Access
  • Hash Join算法
    • In-Memory Join(CHJ)
    • On-Disk Hash Join
  • 参考链接

在8.0.18之前,MySQL只支持NestLoopJoin算法,最简单的就是Simple NestLoop Join,MySQL针对这个算法做了若干优化,实现了Block NestLoop Join,Index NestLoop Join和Batched Key Access等,有了这些优化,在一定程度上能缓解对HashJoin的迫切程度。但是HashJoin的支持使得MySQL优化器有更多选择,SQL的执行路径也能做到更优,尤其是对于等值join的场景。

NestLoopJoin算法

长期以来,在MySQL中执行联接的唯一算法是嵌套循环算法的变体。

Simple Nested-Loop Join

如果我们执行这样一条等值查询语句:

select * from t1 straight_join t2 on (t1.a=t2.b);

由于表 t2 的字段 b 上没有索引,每次到 t2 去匹配的时候,就要做一次全表扫描。就相当于是双for循环。如果 t1 和 t2 都是 10 万行的表(当然了,这也还是属于小表的范围),就要扫描 100 亿行。
SimpleNestLoopJoin显然是很低效的,对内表需要进行N次全表扫描,实际复杂度是N*M,N是外表的记录数目,M是记录数,代表一次扫描内表的代价。为此,MySQL针对SimpleNestLoopJoin做了若干优化。

Index Nested-Loop Join

如果我们能对内表的join条件建立索引,那么对于外表的每条记录,无需再进行全表扫描内表,只需要一次Btree-Lookup即可,整体时间复杂度降低为N*O(logM)。
再来看看这一句

select * from t1 straight_join t2 on (t1.a=t2.a);

在这条语句里,被驱动表 t2 的字段 a 上有索引,join 过程用上了这个索引,因此这个语句的执行流程是这样的:
在这里插入图片描述
执行流程示意图如下:
在这里插入图片描述
在这里插入图片描述
对比HashJoin,对于外表每条记录,HashJoin是一次HashTable的search,当然HashTable也有build时间,还需要处理内存不足的情况,不一定比INLJ好。

Block Nested-Loop Join

MySQL采用了批量技术,即一次利用join_buffer_size缓存足够多的记录,每次遍历内表时,每条内表记录与这一批数据进行条件判断,这样就减少了扫描内表的次数,如果内表比较大,间接就缓解了IO的读压力。
Simple Nested-Loop Join 与 Block Nested-Loop Join从时间复杂度上来说,这两个算法是一样的。但是,Block Nested-Loop Join是内存操作,速度上会快很多,性能也更好。
示意图如下:
在这里插入图片描述

Batched Key Access

IndexNestLoopJoin利用join条件的索引,通过Btree-Lookup去匹配减少了遍历内表的代价。如果join条件是非主键列,那么意味着大量的回表和随机IO。BKA优化的做法是,将满足条件的一批数据按主键排序,这样回表时,从主键的角度来说就相对有序,缓解随机IO的代价。BKA实际上是利用了MRR特性(MultiRangeRead),访问数据之前,先将主键排序,然后再访问。主键排序的缓存大小通过参数read_rnd_buffer_size控制。

Hash Join算法

NestLoopJoin算法简单来说,就是双重循环,遍历外表(驱动表),对于外表的每一行记录,然后遍历内表,然后判断join条件是否符合,进而确定是否将记录吐出给上一个执行节点。从算法角度来说,这是一个M*N的复杂度。HashJoin是针对equal-join场景的优化,基本思想是,将外表数据load到内存,并建立hash表,这样只需要遍历一遍内表,就可以完成join操作,输出匹配的记录。如果数据能全部load到内存当然好,逻辑也简单,一般称这种join为CHJ(Classic Hash Join),之前MariaDB就已经实现了这种HashJoin算法。如果数据不能全部load到内存,就需要分批load进内存,然后分批join,下面具体介绍这几种join算法的实现。

In-Memory Join(CHJ)

HashJoin一般包括两个过程,创建hash表的build过程和探测hash表的probe过程。
1).build phase
遍历外表,以join条件为key,查询需要的列作为value创建hash表。这里涉及到一个选择外表的依据,主要是评估参与join的两个表(结果集)的大小来判断,谁小就选择谁,这样有限的内存更容易放下hash表。
2).probe phase
hash表build完成后,然后逐行遍历内表,对于内表的每个记录,对join条件计算hash值,并在hash表中查找,如果匹配,则输出,否则跳过。所有内表记录遍历完,则整个过程就结束了
在这里插入图片描述

On-Disk Hash Join

CHJ的限制条件在于,要求内存能装下整个外表。在MySQL中,Join可以使用的内存通过参数join_buffer_size控制。如果join需要的内存超出了join_buffer_size,那么CHJ将无能为力,只能对外表分成若干段,每个分段逐一进行build过程,然后遍历内表对每个分段再进行一次probe过程。假设外表分成了N片,那么将扫描内表N次。这种方式当然是比较弱的。

在MySQL8.0中,如果join需要内存超过了join_buffer_size,build阶段会首先利用hash算将外表进行分区,并产生临时分片写到磁盘上;然后在probe阶段,对于内表使用同样的hash算法进行分区。由于使用分片hash函数相同,那么key相同(join条件相同)必然在同一个分片编号中。接下来,再对外表和内表中相同分片编号的数据进行CHJ的过程,所有分片的CHJ做完,整个join过程就结束了。这种算法的代价是,对外表和内表分别进行了两次读IO,一次写IO。相对于之之前需要N次扫描内表IO,现在的处理方式更好。
顺序为:外表的分片、内表分片、哈希连接
在这里插入图片描述

参考链接

join语句怎么优化?
MySQL8.0 新特性 Hash Join
哈希加入MySQL 8
MySQL · 新特征 · MySQL 哈希连接实现介绍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377065.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何解决迅雷插件导致IE10崩溃的问题

Windows 8里面带的IE10酷不酷?沉浸式界面果然不同凡响,IE10让人几乎认不出来了!这是微软的浏览器么?上面这张图是Windows8下Metro UI的新界面IE10,不过当我们切换回传统桌面的时候,也有IE10的经典版的。好吧…

UNITY3D与iOS交互解决方案

原地址:http://bbs.18183.com/thread-456979-1-1.html 本帖最后由 啊,将进酒 于 2014-2-27 11:17 编辑 “授人以鱼,不如授人以渔”,以UNITY3D调用iOS版的91SDK为例,利用C# / C / OBJ-C交互原理,本文将详细介绍UNITY3D与iOS之间交互…

c:if equal_C ++中的std :: equal()

c:if equalequal()作为STL函数 (equal() as a STL function) Syntax: 句法: bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2);Where, 哪里, InputIterator1 first iterator to start of the first sequence range I…

《DBNotes:Buffer Pool刷脏页细节以及改进》

本笔记知识沿用之前DBNotes: Buffer Pool对于缓冲页的链表式管理的部分知识 目录获取一个空闲页的源码逻辑Page_Cleaner_ThreadLRU_Manager_ThreadHazard Pointer作为驱逐算法改进参考获取一个空闲页的源码逻辑 任何一个读写请求都需要从Buffer pool来获取所需页面。如果需要的…

WordPress删除数据中标题重复文章的方法

一种是删除重复的方法是:使用插件,大家可以去官网上下载 二种删除重复的方法是:登录数据库,使用sql语句删除,具体的语句为如下代码: CREATE TABLE my_tmp AS SELECT MIN(ID) AS col1 FROM wp_posts GROUP BY post_titl…

hibernate配置

hibernate.cfg.xml <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd&quo…

html中表单元素_HTML中的表单元素

html中表单元素1)<input>元素 (1) The <input> Element) The <input> element is used to get input from the user in an HTML form. <input>元素用于以HTML形式从用户获取输入。 <input> tag is used to get input using input element, the …

《搜索算法——DFS、BFS、回溯》

目录深搜200. 岛屿数量695. 岛屿的最大面积130. 被围绕的区域547. 省份数量417. 太平洋大西洋水流问题回溯广搜111. 二叉树的最小深度752. 打开转盘锁深搜与广搜结合934. 最短的桥深搜 深搜DFS&#xff0c;在搜索到一个新节点时&#xff0c;立即对该新节点进行遍历&#xff0c…

AP in R

AP聚类算法是目前十分火的一种聚类算法&#xff0c;它解决了传统的聚类算法的很多问题。不仅简单&#xff0c;而且聚类效果还不错。这里&#xff0c;把前两天学习的AP算法在R语言上面的模拟&#xff0c;将个人笔记拿出来与大家分享一下&#xff0c;不谈AP算法的原理&#xff0c…

nginx 模块解析

nginx的模块非常之多&#xff0c;可以认为所有代码都是以模块的形式组织&#xff0c;这包括核心模块和功能模块&#xff0c;针对不同的应用场合&#xff0c;并非所有的功能模块都要被用到&#xff0c;附录A给出的是默认configure&#xff08;即简单的http服务器应用&#xff09…

python关键字和保留字_Python关键字

python关键字和保留字关键词 (Keywords) Keywords are the reserved words in Python programming language (and, any other programming languages like C, C, Java, etc) whose meanings are defined and we cannot change their meanings. In python programming languages…

《LeetcodeHot100非困难题补录》

最近比较闲&#xff0c;也比较焦虑&#xff0c;刷刷题吧 目录11. 盛最多水的容器22. 括号生成31. 下一个排列48. 旋转图像49. 字母异位词分组56. 合并区间75. 颜色分类79. 单词搜索114. 二叉树展开为链表141. 环形链表148. 排序链表152. 乘积最大子数组169. 多数元素207. 课程表…

Java里String.split需要注意的用法

我们常常用String的split()方法去分割字符串&#xff0c;有两个地方值得注意&#xff1a; 1. 当分隔符是句号时(".")&#xff0c;需要转义&#xff1a; 由于String.split是基于正则表达式来分割字符串&#xff0c;而句号在正则表达式里表示任意字符。 //Wrong: //Str…

C# Socket 例子(控制台程序)

服务器代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.IO;namespace TCPListener {class Program{static void Main(string[] args){const int BufferSize 1024;Con…

Scala中的值类

Value classes are a special mechanism in Scala that is used to help the compiler to avoid allocating run time objects. 值类是Scala中的一种特殊机制&#xff0c;用于帮助编译器避免分配运行时对象。 This is done by defining a subclass of AnyVal. The only parame…

《MySQL8.0.22:Lock(锁)知识总结以及源码分析》

目录1、关于锁的一些零碎知识&#xff0c;需要熟知事务加锁方式&#xff1a;Innodb事务隔离MVCC多版本并发控制常用语句 与 锁的关系意向锁行级锁2、锁的内存结构以及一些解释3、InnoDB的锁代码实现锁系统结构lock_sys_tlock_t 、lock_rec_t 、lock_table_tbitmap锁的基本模式的…

关于ORA-04021解决办法(timeout occurred while waiting to lock object)

某个应用正在锁定该表或者包 表为 select b.SID,b.SERIAL#,c.SQL_TEXT from v$locked_object a, v$session b, v$sqlarea c where a.SESSION_ID b.SID and b.SQL_ADDRESS c.ADDRESS and c.sql_text like %table_name% 包为 select B.SID,b.USERNAME,b.MACHINE FROM V$ACCESS …

HtmlAutoTestFrameWork

前段时间做的自动化测试的是Silverlight的&#xff0c;框架都已经搭好。突然测试发现这里还有一个要发送邮件的html页面&#xff0c;并且将另外启动浏览器&#xff0c;于是今天下午把这个html的也写出来。用法 &#xff1a; HtmlAutoTestFrameWork htf new HtmlAutoTestFrameW…

L8ER的完整形式是什么?

L8ER&#xff1a;稍后 (L8ER: Later) L8ER is an abbreviation of "Later". L8ER是“ Later”的缩写 。 It is an expression, which is commonly used in messaging or chatting on social media networking sites like Facebook, Yahoo Messenger, and Gmail, etc…

Randomize select algorithm 随机选择算法

从一个序列里面选择第k大的数在没有学习算法导论之前我想最通用的想法是给这个数组排序&#xff0c;然后按照排序结果返回第k大的数值。如果使用排序方法来做的话时间复杂度肯定至少为O&#xff08;nlgn&#xff09;。 问题是从序列中选择第k大的数完全没有必要来排序&#xff…