Nested loop(PostgreSQL 14 Internals翻译版)

本文详细解释了SQL连接的不同类型,如内连接、外连接、嵌套循环、外连接方法(如PostgreSQL的nestedloopjoin、hashjoin、mergejoin),以及如何进行基数预估、选择性计算和成本估算。还讨论了并行模式在连接操作中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

连接类型和方法

连接是SQL语言的一个关键特性;它们是其力量和灵活性的基础。行集(要么直接从表中检索,要么作为某些其他操作的结果接收)总是成对连接。

有几种类型的连接:

  • 内连接。 内连接(指定为“INNER JOIN”或简称为“JOIN”)由满足特定连接条件的两个集合的行对组成。连接条件将一组行的一些列与另一组行的一些列结合起来;所有涉及的列都构成连接键。
    如果连接条件要求两个集合的连接键相等,这样的连接称为等连接(equi-join) ;这是最常见的连接类型。
    两个集合的笛卡尔积(CROSS JOIN) 包含了这些集合的所有可能的行对——它是具有真条件的内连接的一种特殊情况。

  • 外连接。 左外部连接(指定为“LEFT OUTER”或简称“LEFT JION”)通过左集中没有与右集中匹配的行(相应的右侧列填充为NULL值)扩展内部连接的结果。
    对于右连接(RIGHT JOIN)也是如此,直到集合的排列。
    完整的外部连接(指定为FULL JOIN)包括左外部连接和右外部连接,添加没有找到匹配的右侧和左侧行。

  • 反连接(ANTI-JOIN)及半连接(SEMI-JOIN)。 半连接看起来很像内部连接,但它只包括左集中与右集中有匹配的行(即使有几个匹配,也只包括一行)。
    反连接包括一个集合中在另一个集合中没有匹配的行。
    SQL语言没有显式的半连接和反连接,但是使用像“EXISTS”和“NOT EXISTS”这样的谓词也可以达到同样的结果。

所有这些连接都是逻辑操作。例如,内部连接通常被描述为已经清除了不满足连接条件的行的笛卡尔积。但是在物理级别上,内连接通常是通过成本较低的方式实现的。

PostgreSQL提供几种连接方法:

  • nested loop join
  • hash join
  • merge join

连接方法是实现SQL连接的逻辑操作的算法。这些基本算法通常具有为特定连接类型量身定制的特殊风格,即使它们可能只支持其中的一些。例如,嵌套循环支持内部连接(在计划中由嵌套循环节点表示)和左外部连接(由嵌套循环左连接节点表示),但它不能用于完全连接。
相同算法的某些风格也可以用于其他操作,例如聚合。
不同的连接方式在不同的条件下表现最佳;优化器的工作是选择最具成本效益的一种。

嵌套循环连接(Nested loop Joins)

嵌套循环连接函数的基本算法如下:外部循环遍历第一个集合(称为外部集合)的所有行。对于这些行中的每一行,将遍历第二组(称为内部集合)的行,以查找满足连接条件的行。 每个找到的对都会作为查询结果的一部分立即返回。
该算法访问内部集合的次数与外部集合的行数相同。因此,嵌套循环连接的效率取决于以下几个因素:

  • 行外部集合的基数
  • 可用的访问方法,可以有效地获取内部集所需的行
  • 循环访问内部集合的同一行

笛卡尔积

不管集合中有多少行,嵌套循环连接是找到笛卡尔积的最有效方法:
在这里插入图片描述
嵌套循环节点使用上述算法执行连接。它总是有两个子节点:在计划中显示较高的一个对应于外部行集,而较低的一个代表内部行集。

在本例中,内部集合由Materialize节点表示。该节点返回从其子节点接收到的行,并保存它们以备将来使用(这些行在内存中累积,直到它们的总大小达到work_mem;然后PostgreSQL开始将它们溢出到磁盘上的临时文件中)。如果再次访问,该节点将读取累积的行,而不调用子节点。因此,执行器可以避免再次扫描整个表,而只读

### 嵌套循环连接算法及其数据库中的应用 嵌套循环连接(Nested Loop Join, NLJ)是一种常见的关系型数据库查询优化器使用的物理实现方法之一。它通过遍历两个数据集来查找匹配的记录组合,通常用于处理较小的数据表或者当外层表非常小时。 #### 工作原理 NLJ 的基本工作流程如下:对于外部输入表中的每一行,内部输入表都会被完全扫描一次以寻找满足条件的匹配项。如果存在索引,则可以利用该索引来加速访问过程[^1]。这种方法特别适合于那些具有高度选择性的连接谓词场景下运行良好,因为这样能够减少不必要的 I/O 开销。 #### 使用情况分析 在实际操作过程中,SQL Server 和其他主流的关系型数据库管理系统可能会自动决定何时采用 Nested Loops Joins 来执行特定类型的 JOIN 查询语句。例如,在某些情况下,如果两张待关联表格之间存在着良好的分区对齐特性(pre-joining aligned tables),那么系统就更倾向于选用这种高效的联接方式来进行多阶段并行化计算。 另外需要注意的是,并不是所有的数据库都支持相同的功能集合;比如当我们对比 SQL Server、MySQL 及 PostgreSQL 这三种不同平台所提供的特性和功能差异时就会发现它们各自有所侧重之处[^3]。因此,在具体开发项目之前应该充分考虑目标环境的支持程度以及性能表现等因素后再做最终抉择。 下面给出一段 Python 中模拟简单 nested loop join 功能的小例子: ```python def simple_nested_loop_join(table_a, table_b, condition_func): result = [] for row_a in table_a: for row_b in table_b: if condition_func(row_a, row_b): # Apply the given condition function. combined_row = {**row_a, **row_b} # Combine rows into one dictionary. result.append(combined_row) return result ``` 此函数接受三个参数分别是代表左表`table_a`,右表 `table_b`还有用来判断两行是否符合条件的一个回调函数`condition_func`. 它会逐一遍历每一对可能来自这两个列表内的元素并对他们调用传入的方法去检测是否存在对应关系; 如果有则将其合并成一个新的字典形式加入到结果集中最后返回整个列表.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据源的港湾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值