首页 > 数据库 > 程序员必备的数据库知识 2:Join 算法

程序员必备的数据库知识 2:Join 算法

时间:2023-02-08 17:02:15浏览次数:57  
标签:NLJ Join 必备 连接 程序员 Hash 关联 数据库

前言

连接(Join)是关系数据库重要特性,它和事务常被作为数据库与文件系统的两个重要区别项。程序员江湖一直流传着某某 baba 的神秘开发宝典,其中数据库部分有重要一条避免过多表的 Join,奈何 Join 特性实在是好用,广大程序员们无视着宝典的谆谆教诲,依旧每天乐此不疲的使用这 Join 特性。那数据库有哪些连接算法呢?它们的实现方式是怎样呢?它们之间又有什么区别呢?为什么需要这么多不同的连接算法呢?如果你也好奇这些问题,那么请继续往下阅读,本文将逐一回答上述问题。


关联算法简介

关系型数据库主要有三种 Join 算法:Nested Loop Join,Hash Join、 Merge Join,像 Oracle、SqlServer 、DB2 这几位数据库中的老炮均支持三种 Join 方式;MySQL 长久以来只支持 NLJ 或其变种,直到8.0.18 版本后才有限的支持 Hash Join。在 「​​程序员必备的数据库知识:数据存储结构​​」一文中介绍了数据库几种常见的数据存储结构,存储引擎之上是计算引擎。以 MySQL 数据库为例,计算引擎层通常包括 SQL 接口、解析器、查询优化器、缓存等组件,数据库 Join 实现就在计算引擎的查询优化器中。

 程序员必备的数据库知识 2:Join 算法_MySQL

以 MySQL 数据库为例,计算引擎层

然而数据库具体选择哪种连接算法,是由本身决定的,主要根据当前的优化器模式、表大小、连接列是否有索引和排序等因素决定。

多表连接方式又分为:内连接(等值连接)、外连接和交叉连接,外连接又分为:左外连接、右外连接和全外连接。对于不同方式的连接查询,使用相同的 Join 算法也会有不同的成本产生,这和实现方式紧密相关的。本文不涉及同一个 Join 算法在不同连接方式的情况。


Nested Loop Join

NLJ 是 MySQL 最重要的连接方式,也是 MySQL 长期唯一支持的连接方式,直到 8.0.18 版本 MySQL 才有限的支持 Hash Join。那什么是 NLJ 呢?从概念上讲,NLJ 相当于两个嵌套循环,用第一张表做 Outter Loop,第二张表做 Inner Loop,Outter Loop 的每一条记录跟 Inner Loop 的记录作比较,最终符合条件的就将该数据记录。

可以用以下伪代码表示:

 程序员必备的数据库知识 2:Join 算法_数据_02

NLJ 可以用伪代码表示

如果忽略内存和 CPU 的时间,它的成本是:

Cost(NLJ) = Read(M) + M * Read(N) (其中M和N表示需要读两个关联表中的数据行数)

NLJ 的算法比较简单,并且对 Join 的连接条件没有特殊要求(Hash Join 通常只支持等值,Merge Join 一般不支持不等和like),在有索引过滤性较好的 OLTP 场景下,它的查询效率很高。缺点也同样明显,由于它的成本是:Read(M) + M * Read(N) 。在 OLAP 需要大表间 Join 场景下,它的查询效率变得比较差。在 MySQL 中 NLJ 还有两个变种:Index Nested Loop Join(INLJ)、Block Nested Loop Join(BNLJ),本文不涉及这方面的扩展,有兴趣的同学可以深入研究。


Hash Join

Hash Join 是Oracle、SQLServer 、PostgreSQL 中重要的关联算法,当两个表关联时,选择一张表按照 join 条件给的列构建 hash 表,然后将第二张表的每行记录去探测 hash 表中的数据,如果符合连接条件就输出该数据。前一张表我们叫做 build 表,后一张表我们的叫做 probe 表。为了减少内存使用量,通常选择小表作为 hash 表,大表作为 probe 表。

 程序员必备的数据库知识 2:Join 算法_算法_03

Hash Join

经典 Hash Join 主要有两个步骤:选择 hash 表,扫描该表并创建 hash 表;将另一个作为 probe 表,扫描每一行数据,然后在 hash 表中找寻对应的满足条件的记录。忽略内存和 CPU 时间,它的成本是:

Cost(HJ) = Read(M) + Read(N)

Hash Join 需要把表放到内存中,如果内存不够怎么办?为了处理这种情况,又诞生一些 Hash Join 的变种,比如 Grace Hash Join 。简单说是通过分区方式实现,根据关联字段将两个表的数据分区,然后对同一分区的数据再进行原生 Hash join 的 build 与 probe 过程,最后将所有分区的数据合并成最后的结果集。当然在实际中会更复杂,比如在大数据量的情况下,有概率出现不同数据的 HASH 值却是相同的问题。

总的来说,Hash Join 是处理大表间 Join 的不错选择。MySQL 在 8.0.18 前一直没有 Hash join 的实现,甚至在5.5以前只有最原始的 NLJ,5.5后才有 NLJ 优化变种的 B(Block)NLJ。但 Oracle 早在7.3版本之后就引入了 Hash join 算法,在 OLAP 领域中 Hash join 更是绝对的标配,Greenplum 和 Spark SQL 就充分利用了它。但是它也有缺点,比如只能使用等值查询、需要更多的内存资源等。


Merge Join

Merge Join ,准确地说它叫 Sort Merge Join, 在合并关联查询时要先确保两个关联表是按关联字段相同排序的。如果关联字段有可用的索引(配合聚集索引服用效果更佳)并且排序一致,则可以直接进行Merge 操作,否则要先对关联表按照关联字段进行一次排序。排好序后,再从每个表取一条记录开始匹配,如果符合关联条件,则放入结果集中;否则将关联字段值较小的记录抛弃,从这条记录对应的表中取下一条记录继续进行匹配,直到整个循环结束。因此它的成本是这样的:

COST(MJ) = Read(M) + Sort(M) + Read(N) + Sort(N)

显然,Merge Join 适合在关联列上有索引的表,最好在关联列还有相同的排序方式,在这种情况下它的关联查询效率是最高的。但是关联字段如果没有排序,那么它的排序阶段则比较耗时。


总结

通过前文的分析,我们基本可以回答文章最开头的几个问题了,更多信息可以看下表格。另外,除了上述常见的三种数据库Join方式外,还有 Hive 支持 Map Join 和 Reduce Join。

 程序员必备的数据库知识 2:Join 算法_数据库_04

常见 Join 算法的优势对比总览

作者

司马辽太杰是 ​​NineData​​​ 工程师。​​NineData​​​ 向企业和个人提供高效、安全的数据库 SQL 开发、数据库备份、数据复制/迁移/集成、数据对比等功能,是一个 SaaS 服务开箱即用,可以快速提升企业 SQL 开发效率,保障企业数据安全。​​NineData​​​ 地址:​​NineData-让每个人用好数据和云-玖章算术​

标签:NLJ,Join,必备,连接,程序员,Hash,关联,数据库
From: https://blog.51cto.com/ninedata/6044642

相关文章

  • 程序员必备的数据库知识 2:Join 算法
    前言连接(Join)是关系数据库重要特性,它和事务常被作为数据库与文件系统的两个重要区别项。程序员江湖一直流传着某某baba的神秘开发宝典,其中数据库部分有重要一条避免过多......
  • 程序员大杀器?带你玩转ChatGPT
    作者:京东零售栗鸿宇ChatGPT简介ChatGPT是一款基于AI技术的机器人对话软件,它能够与用户进行智能化的聊天对话,帮助用户解决日常生活中的问题,为用户提供丰富的信息和服务。它......
  • 使用joinablequeue优化生产者消费者问题
    #Joinablequeue队列'''put存放get获取task_done计数器属性值-1join配合task_done使用,阻塞put一次数据,队列的内置计数器属性值+1get一次数据,通过task_done让......
  • IGMP V3 Membership Report / Join group
    No.TimeSourceDestinationProtocolInfo80.165110192.168.43.135224.0.0.22IGMPV3MembershipReport/Joingroup224.0.0.252......
  • 程序员大杀器?带你玩转ChatGPT
    作者:京东零售栗鸿宇ChatGPT简介ChatGPT是一款基于AI技术的机器人对话软件,它能够与用户进行智能化的聊天对话,帮助用户解决日常生活中的问题,为用户提供丰富的信息和服务......
  • 来看一个 ChatGPT 有关程序员的笑话
    我们把ChatGPT集成到我们的公众号里面了,忍不住每天都想问个笑话。现在的问题就是ChatGPT的返回时间经常性超过4秒。  我们的公众号又是个人认证公众号,无法发......
  • #yyds干货盘点# LeetCode程序员面试金典:括号
    题目:括号。设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合。说明:解集不能包含重复的子集。例如,给出 n=3,生成结果为:[ "((()))", "(()())", "(())()", ......
  • ChatGPT横空出世,虽然会改BUG,但程序员也不用慌
    现实版“moss”?最近,科技界、金融界、教育界,都被ChatGPT刷屏了。ChatGPT突然蹿红,出乎了所有人的意料,包括团队。但大风之下,争议也随之而来。什么是ChatGPT?简单来说就是一台......
  • 2023无死角java学习必备知识点有哪些?
    前奏与工具:学习路线梳理➾JDK工具➾JDK新特性➾IDEA工具基础语言:java基础➾设计模式➾数据结构与算法数据库与JDBC:MySQL➾JDBCWEB基础:Javaweb(HTML/CSS/JS/Tomcat......
  • 程序员是否需要精通业务
    但在今天,这个世界最不缺的应该就是码农了,未来最廉价的也将是码农。仅有泛泛一技,在未来并不吃香,因为那是要被机器人所取代的。这个世界,缺的是技术过硬又精通业务的工......