Merge Joins(PostgreSQL 14 Internals翻译版)

news/2024/7/9 23:22:03 标签: postgresql

合并连接处理按连接键排序的数据集,并返回以类似方式排序的结果。输入集可以在索引扫描后预先排序;否则,执行者必须在实际合并开始之前对它们进行排序。

归并排序集

让我们看一个合并连接的例子;它在执行计划中由Merge Join节点表示:

在这里插入图片描述
优化器更喜欢这种连接方法,因为它返回排序的结果,如ORDER BY子句定义的那样。在选择计划时,优化器会注意数据集的排序顺序,除非确实需要,否则不会执行任何排序。例如,如果合并连接产生的数据集已经具有适当的排序顺序,则可以在随后的合并连接中使用:

在这里插入图片描述

首先要连接的表是机票和登机牌;它们都有一个复合主键(ticket_no,flight_id),结果按这两列排序。然后将生成的行集与票券表连接,票券表按ticket_no列排序。

连接只需要对两个数据集进行一次传递,并且不占用任何额外的内存。它使用两个指针指向内部集和外部集的当前行(最初是第一行)。

如果当前行的键不匹配,则其中一个指针(引用具有较小键的行)将向前移动到下一行,直到找到匹配。连接的行返回到上面的节点,并且内部集合的指针向前移动一位。操作将继续,直到其中一个集合结束。

该算法处理内部集合的副本,但外部集合也可以包含它们。因此,必须改进算法:如果在外部指针前进后键保持不变,则内部指针返回到第一个匹配行。因此,外部集合的每一行都将与具有相同键的内部集合的所有行相匹配。

对于外部连接,算法进一步调整了一点,但它仍然基于相同的原理。

合并连接条件只能使用相等操作符,这意味着只支持相等连接(尽管对其他条件类型的支持目前也在进行中)。

成本预估。 进一步查看刚刚的例子:

在这里插入图片描述
连接的启动成本至少包括所有子节点的启动成本。

通常,在找到第一个匹配之前,可能需要扫描外部或内部集合的一部分。可以通过比较(基于直方图)两个集合中最小的连接键来估计这个比例。但在这种特殊情况下,两个表中的票号范围是相同的。

总成本包括从子节点获取数据的成本和计算成本。

因为一旦其中一个集合结束,连接算法就会停止(当然,除非执行外部连接),所以可能只会部分扫描另一个集合。为了估计被扫描部件的尺寸,我们可以比较两个集合中的最大键值。在本例中,两个集合都将被完整读取,因此连接的总成本包括两个子节点的总成本之和。

此外,如果存在任何重复,则内部集合的某些行可能被扫描多次。估计的重复扫描次数等于连接结果的基数与内部集合的基数之差。在这个查询中,这些基数是相同的,这意味着集合不包含重复项。

该算法比较两个集合的连接键。一次比较的代价是在cpu_operator_cost值上估计的,而估计的比较次数可以看作是两个集合的行数之和(由重复引起的重复读取次数增加)。像往常一样,结果中包含的每一行的处理成本都是在cpu_tuple_cost值上估计的。

因此,在这个例子中,连接的成本估计如下:

在这里插入图片描述

并行模式

虽然合并连接没有并行特性,但它仍然可以在并行计划中使用。

外部集合可以由多个工作进程并行扫描,但内部集合总是由每个工作进程全部扫描。

由于并行散列连接几乎总是更便宜,我将关闭它一段时间:

在这里插入图片描述
下面是一个使用合并连接的并行计划的例子:

在这里插入图片描述
在并行计划中不允许完全和右外部合并连接。

修改

合并连接算法可用于任何类型的连接。唯一的限制是完整和右外部连接的连接条件必须包含合并兼容的表达式(“外列等于内列”或“列等于常量”)。内部连接和左外部连接只是根据不相关的条件过滤连接结果,但对于完全连接和右连接,这种过滤是不适用的。

下面是一个使用合并算法的全连接示例:

在这里插入图片描述

内部和左合并连接保留排序顺序。但是,完全外部连接和右外部连接不能保证这一点,因为NULL值可能会插入外部集的有序值之间,从而破坏排序顺序。为了恢复所需的顺序,规划器在这里引入Sort节点。自然地,它增加了计划的成本,使散列连接更有吸引力,所以计划器选择这个计划只是因为当前禁用了散列连接。

但是下一个示例不能没有散列连接:嵌套循环根本不允许完全连接,而由于不支持连接条件而不能使用合并。因此,无论enable_hashjoin参数值如何,都将使用散列连接:

在这里插入图片描述
让我们恢复之前禁用的哈希连接功能:

在这里插入图片描述


http://www.niftyadmin.cn/n/5114866.html

相关文章

机器人系统 ROS 常用命令行工具

1. 启动ros 主节点 roscore roscore运行成功如图: 1.1 rosrun 启动服务节点 例子:启动一个小乌龟节点 rosrun turtlesim turtlesim_node运行结果如图: 1.2 启动键盘控制 打开新的命令窗口,启动turtle_teleop_key 节点 rosr…

cmake工程出现“CMAKE_CUDA_ARCHITECTURES must be non-empty if set.“的解决方法

解决方法1: cmake工程出现“CMAKE_CUDA_ARCHITECTURES must be non-empty if set.“的解决方法 – The CUDA compiler identification is unknown CMake Error at /usr/share/cmake-3.24/Modules/CMakeDetermineCUDACompiler.cmake:602 (message): Failed to detect a defaul…

VS2022ide下使用C++实现简谐振动,C语言程序设计简谐运动的模拟,C语言课程设计简谐振动实验的模拟。

背景: C语言课程设计简谐振动实验的模拟 《C语言程序设计》 课程设计报告 题 目简谐振动实验的模拟姓 名 学 号 同组人员 学 号 年级专业09电子信息工程(2)班指导教师 完成日期2010年6月13日 目 录 一、问题描述 二、基本要求 三、系统分析和过程 四、流程…

信号继电器驱动芯片(led驱动芯片)

驱动继电器需要配合BAV99(防止反向脉冲)使用 具体应用参考开源项目 电阻箱 sbstnh/programmable_precision_resistor: A SCPI programmable precision resistor (github.com) 这个是芯片的输出电流设置 对应到上面的实际开源项目其设置电阻为1.5K&…

深入篇【Linux】学习必备:进程环境变量/进程切换

深入篇【Linux】学习必备:进程环境变量/进程切换 Ⅰ.环境变量Ⅱ.深层意义Ⅲ.全局属性Ⅳ.进程切换 Ⅰ.环境变量 1.环境变量是什么?:环境变量是系统提供的一组name/value形式的变量,不同的环境变量有不同的用户。 一般是用来指定操作…

caffeine学习笔记

在项目中使用了caffeine,本文将会介绍其工具的原理 1.caffenine的缓存淘汰策略 Window-TinyLFU 1.新增缓存数据首先写入 Window Cache 区域。当 Window Cache 空间满时,LRU 算法发挥作用,最久未被访问的缓存项会被移出 Window Cache 。这个被…

idea必装的插件 Spring Boot Helper 插件(创建 Spring Boot 项目)

Spring Spring让Java程序更加快速,简单和安全.Spring对于速度、简单性和⽣产⼒的关注使其成为 世界上最流⾏的Java框架。Spring官⽅提供了很多开源的项⽬,覆盖范围从Web开发到⼤数据,Spring发展到了今天,已经形成了⾃ ⼰的⽣态圈.我们在开发时,也倾向于使⽤Spring官⽅提供的技术…

C语言里的static变量其他语言是看不上还是学不去?

C语言里的static变量其他语言是看不上还是学不去? static变量在C语言中被用于具有静态存储期的局部变量或全局变量。它有以下几个特点: 1. 静态存储期:static变量在程序执行时分配内存,直到程序结束才会释放,其生命周期与程序的…