SQL基础理论篇(七):多表关联的连接算法

news2024/9/24 5:27:16

文章目录

  • 简介
  • Nested Loops
  • Merge Join
  • Hash Join
  • 总结
  • 参考文献

简介

多表之间基础的关联算法一共有三种:

  • Hash Join
  • Nested Loops
  • Merge Join

还有很多基于这三种基础算法的变体,以Nested Loops为例,就有用于in和exist的半连接(Nested Loops Semi)算法,以及用于not in和not exists的反连接(Nested Loops Anti)算法等等。这里就不展开介绍了,有兴趣可以再专门搜搜。

Nested Loops

中文名叫嵌套循环,这种连接方式可以简单的用下图来展示:

在这里插入图片描述

上图来自参考文献2.

如果内表中的连接列有索引的话,内表就可以做index scan(索引扫描),否则的话,内表就只能做tab scan(全表扫描)了。

假设我们有一个外表outer, 一个内表inner,连接列c,嵌套循环实际上就是:

for i in outer:
	for j in inner:
        if i.c = i.c:
            # do something

这就是利用嵌套查询来做连接的全过程。

如果inner表的c列有索引,那内层循环就很快了,直接走index scan即可,如果没有,那就只能tab scan扫描全表了。如果没有索引的话,outer表有多少行记录,inner表就要 全表扫描多少次。(所以内层没有索引的话是很恐怖的)

至于外层outer表有没有索引,就无所谓了,反正他总是要做tab scan,取出每一行来跟inner表比较的。

有个小问题,嵌套循环中,如果连接条件使用了不等值连接,那内表还能走索引吗?

不等式!=会导致索引失效,使用函数会导致失效,但范围查询一般不会使索引失效,如<、>=之类的。(注意是一般情况, 如果优化器认为通过索引扫描的行记录数超过全表的10%~30%,那么它可能会自动变成全表扫描,放弃走索引

Merge Join

也称合并连接。

merge join实际上就是把两个有序队列(存在索引,或者无索引但是有序)进行连接,需要两端都要有序,所以不像Nested Join一样不断的循环内部的表。另外,Merge Join需要表连接条件中至少有一个等式,查询分析器才会去选择Merge Join。

merge join的过程可以用下面几个图来解释(同样来自参考文献2):

在这里插入图片描述

首先从两个表中各选取一行,比较,如果匹配,则返回匹配行;如果不匹配,则有较小值的表+1行,可认为是拥有较小值的表,指针后移一位。

在这里插入图片描述

但是如果当前两表并不是有序表(但存在索引),你需要显式的sort之后才能merge join的话,那么使用hash join是效率更高的选择。但也并不绝对,如果查询中已经存在了order by、group by、distinct等,那可能会导致查询分析器不得不进行显式排序,既然已经显式sort了,那查询分析器大概率会对sort之后的结果做merge join。

merge join 对不等值连接(除!=、like外)有更好的支持效率。

但是上面的这张图只能说明等式连接下的merge join的执行过程,那不等式连接下的merge join呢?

据说是这样的:

  1. 根据谓词条件访问A表,对A表的结果集按照连接列进行排序,形成R1;
  2. 根据谓词条件访问B表,对B表的结果集按照连接列进行排序,形成R2;
  3. 将R1和R2放入PGA(即SQL内存区);(这也是传说中的,sort merge join的两表只需要做一次扫描的原因,扫一次就写入内存)
  4. R1中取出第一条记录去R2进行匹配,然后取第二条、第三条,直到匹配完R1中的所有记录。由于R1和R2都在内存中,所以这个匹配过程也是在PGA中进行的。

可以发现,这个过程实际上跟嵌套循环很像,但是有个很显著的特点,merge join中内表是排过序的,这意味着,相比嵌套循环,merge join能高效的处理不等值连接

通常情况下,sort merge join并不适合OLTP的系统, 原因是对于OLTP来讲,排序是极其昂贵的操作

Hash Join

哈希连接。

哈希连接在针对大量、无序的数据时,性能均要优于Merge Join和Nested Join。对于连接列没有索引的情况,查询分析器会优先使用Hash Join。所以哈希连接是做大数据集连接时的常用方式。Hash Join只支持等值连接。

哈希连接分为两个阶段:生成和探测阶段

生成阶段,选择其中一个表(一般是量比较小的表)作为输入源,将其每一行都经过散列函数的计算,放入不同的Hash Bucket中。其中用到的Hash Function和Hash Bucket据说是黑盒的。另外,Hash Bucket中的数据无序。

这一阶段可以参照下图:

在这里插入图片描述

探测阶段,对于另一个表,同样针对每一行做散列函数计算,确定其应在的Hash Bucket,然后用这一行跟这个Hash Bucket中的每一行做匹配,匹配成功则返回对应的行。

探测阶段里,用到的表不需要放入内存,只需要把生成阶段里的小表放入内存即可。

由于Hash Join涉及散列函数计算,所以对CPU的消耗会很大,另外其输出的结果也是无序的。如果内存吃紧的话,还会涉及Grace哈希匹配和递归哈希匹配,可能会用到TempDB从而吃掉大量的IO(如果Hash表太大,无法一次构造在内存里,则会分成若干个partition,写入磁盘,所以使用时会多很多的IO)。有兴趣可以自行查找看看。

hash join 如何处理不等式连接问题?

hash join不支持不等值连接,即<>、<、>等,以及like。

事实上,我感觉也是,分成桶也没办法做范围查询之类的。

总结

在这里插入图片描述

出自参考文献2;

需要提一句的是,在MySQL8.0.18发布之前的很长一段时间里,Mysql的连接算法只有一个嵌套循环的变体,被人广为诟病。直到Mysql8.0.18发布后,Mysql才可以使用Hash Join了。

一般来讲,有索引的情况下会优先使用嵌套,没索引的等值连接则优先使用哈希连接。

参考文献

  1. 多表连接的三种方式详解 hash join、merge join、 nested loop
  2. 表的连接方式:NESTED LOOP、HASH JOIN、MERGE JOIN(修改) 写的非常好,推荐看看
  3. 表连接三剑客(嵌套循环连接,哈希连接,排序合并连接)
  4. 实现一个基于嵌套循环策略的两表连接算法_MySQL新特性之哈希连接

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

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

相关文章

【Android Jetpack】Hilt的理解与浅析

文章目录 依赖注入DaggerHiltKoin添加依赖项Hilt常用注解的含义HiltAndroidAppAndroidEntryPointInjectModuleInstallInProvidesEntryPoint Hilt组件生命周期和作用域如何使用 Hilt 进行依赖注入 本文只是进行了简单入门&#xff0c;博客仅当做笔记用。 依赖注入 依赖注入是一…

文档向量化工具(一):Apache Tika介绍

Apache Tika是什么&#xff1f;能干什么&#xff1f; Apache Tika是一个内容分析工具包。 该工具包可以从一千多种不同的文件类型&#xff08;如PPT、XLS和PDF&#xff09;中检测并提取元数据和文本。 所有这些文件类型都可以通过同一个接口进行解析&#xff0c;这使得Tika在…

node实战——koa实现文件上传

文章目录 ⭐前言⭐koa实现文件上传⭐foxapi测试⭐总结⭐结束⭐前言 大家好,我是yma16,本文分享关于node实战——node实战——koa实现文件上传。 本文适用对象:前端初学者转node方向,在校大学生,即将毕业的同学,计算机爱好者。 node系列往期文章 node_windows环境变量配置…

Day35力扣打卡

打卡记录 相邻字符不同的最长路径&#xff08;树状DP&#xff09; 链接 若节点也存在父节点的情况下&#xff0c;传入父节点参数&#xff0c;若是遍历到父节点&#xff0c;直接循环里 continue。 class Solution:def longestPath(self, parent: List[int], s: str) -> in…

《微信小程序开发从入门到实战》学习二十

3.3 开发创建投票页面 3.3.8 使用icon图标文件 原来已经实现了投票选项的增加和修改功能&#xff0c;现在还差删除。现在为每一个选项增加删除按钮&#xff0c;可以以通过icon图标组件实现。 icon常用属性如下&#xff1a; type icon的类型&#xff0c;有success、s…

Linux虚拟机中网络连接的三种方式

Linux 虚拟机中网络连接的三种方式 先假设一个场景&#xff0c;在教室中有三个人&#xff1a;张三、李四和王五&#xff08;这三个人每人有一台主机&#xff09;&#xff0c;他们三个同处于一个网段中&#xff08;192.169.0.XX&#xff09;&#xff0c;也就是说他们三个之间可…

ICASSP2023年SPGC多语言AD检测的论文总结

文章目录 引言正文AbstractRelated ArticleNo.1: CONSEN: COMPLEMENTARY AND SIMULTANEOUS ENSEMBLE FOR ALZHEIMERSDISEASE DETECTION AND MMSE SCORE PREDICTION特征相关模型结构数据处理结果分析 No.2: CROSS-LINGUAL TRANSFER LEARNING FOR ALZHEIMERS DETECTION FROM SPON…

NSS [鹤城杯 2021]Middle magic

NSS [鹤城杯 2021]Middle magic 源码直接给了。 粗略一看&#xff0c;一共三个关卡 先看第一关&#xff1a; if(isset($_GET[aaa]) && strlen($_GET[aaa]) < 20){$aaa preg_replace(/^(.*)level(.*)$/, ${1}<!-- filtered -->${2}, $_GET[aaa]);if(preg_m…

开源与闭源:大模型发展的双重走向

目录 前言开源和闭源的优劣势比较开源的优势闭源的优势 开源和闭源对大模型技术发展的影响对技术发展的影响对数据共享的影响对业务拓展的影响 开源与闭源的商业模式比较开源的商业模式闭源的商业模式 处在大模型洪流中&#xff0c;向何处去&#xff1f;结语 前言 随着人工智能…

【Flink】核心概念:任务槽(Task Slots)

任务槽 每个 worker&#xff08;TaskManager&#xff09;都是一个 JVM 进程&#xff0c;可以在单独的线程中执行一个或多个 subtask。为了控制一个 TaskManager 中接受多少个 task&#xff0c;就有了所谓的 task slots&#xff08;至少一个&#xff09;。 每个任务槽&#xf…

H110主板搭配魔改QNCW升级小记

最近搬家完毕&#xff0c;翻出来一块闲置已久的qncw&#xff0c;隐约记得是买的主板套装&#xff0c;现在主板早已不知踪影&#xff0c;剩下孤零零一个CPU&#xff0c;一起翻出来一个G3900T亮机CPU&#xff0c;应该是同时代的产物。 qncw百度上一搜&#xff0c;发现参数还行&am…

CICD 持续集成与持续交付——jenkins

部署 软件下载&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/ [rootcicd2 ~]# rpm -ivh jdk-11.0.15_linux-x64_bin.rpm[rootcicd2 ~]# yum install -y fontconfig[rootcicd2 ~]# rpm -ivh jenkins-2.432-1.1.noarch.rpm启动服务 [rootcicd2 ~]# systemctl…

【Java】网络编程基础—InetAddress类和URL编程

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;Java ⭐每日一句&#xff1a;为了那个远方&#xff0c;你要奋不顾身 &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️ 文章目录 一.&#x…

Python编程技巧 – 使用字符串(Strings)

Python编程技巧 – 使用字符串&#xff08;Strings) Python Programming Essentials – Using Strings 本文简要介绍如何使用字符串&#xff0c;来进行Python编程。字符串有很多用途&#xff0c;包括输出结果、反馈状态、数据处理以及切片和文本筛选等 1. 字符串 字符串(St…

DevToys:开发者的多功能瑞士军刀,让编程更高效!

DevToys&#xff1a;开发者的多功能瑞士军刀&#xff0c;让编程更高效&#xff01; DevToys 是一款专为开发者设计的实用工具&#xff0c;它能够帮助用户完成日常的开发任务&#xff0c;如格式化 JSON、比较文本和测试正则表达式&#xff08;RegExp&#xff09;。它的优势在于…

开源WIFI继电器之硬件电路

一、原理图 源文件 二、原理图说明 1、器件说明 U4&#xff1a;ESP8285模块 U6&#xff1a;触发器 U3&#xff1a;继电器 2、继电器状态检测说明 检测继电器线圈是否通电来判断继电器是否导通&#xff0c;当Q1不导通时&#xff0c;Q1集电极的电压为3.3V&#xff0c;经…

微机原理练习题_13

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案。&#xff09; 1、十六进制数5BF.C8转换成二进制数是(&#xff09; A. 11011100111111101B B. 010111011011.01101B C. 010110111111.11001B D. 010111011011.11001B 2,最适合…

nodejs+vue慢性胃炎健康管理系统的设计与实现-微信小程序-安卓-python-PHP-计算机毕业设计

随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于慢性胃炎健康管理系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了慢性胃炎健康管理系统&#xff0c; 系统首页、个…

【Android】使用Retrofit2发送异步网络请求的简单案例

添加网络权限到AndroidManifest.xml清单文件 为了让你的Android应用程序能够使用互联网进行通信&#xff0c;你需要在AndroidManifest.xml文件中添加网络权限声明。<uses-permission android:name"android.permission.INTERNET"/> 这个权限应该添加到 Android…

【LeetCode每日一题合集】2023.9.25-2023.10.1(⭐LFU缓存Java数据流花期内花的数量)

文章目录 460. LFU 缓存⭐&#xff08;数据结构题&#xff09;解法1——平衡树 哈希表&#xff08;TreeSet HashMap&#xff09; O ( l o g n ) O(logn) O(logn)解法2——双哈希表 双向链表 O ( 1 ) O(1) O(1) &#xff08;LRU缓存的升级版&#xff09; 2582. 递枕头解法—…