GPDB技术内幕 - SEMI JOIN浅析

2024-04-13 13:20
文章标签 技术 join 浅析 内幕 semi gpdb

本文主要是介绍GPDB技术内幕 - SEMI JOIN浅析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

GPDB技术内幕 - SEMI JOIN浅析

SEMI JOIN顾名思义,半连接,相对于join字段来说,针对外表的一行记录,内表只要有一条满足,就输出外表记录。注意,这里是仅输出外表记录。GPDB中有几种实现方式,本文我们简单聊聊。

从代码中,我们看到SEMI JOIN的类型有3类:

0955d516f25d7d5fd38618319fabc939.png

1、JOIN_SEMI

这是普通实现方式。针对nestloop join、merge join、hash join的inner join来说,只要针对JOIN字段,内表有记录就输出外表记录。以nestloop join为例:

1a09da9e8607945ed5dd6e8e6315a7c1.png

外表和内表记录是无序的,针对外表第一个记录1,遍历内表。内表第一记录为11,不匹配,继续下一条记录;下一条是1,join匹配,输出外表1的值;此时针对外表记录1,就不必继续内表扫描了,join结束,继续外表下一个记录10重新扫描内表进行join条件判断。

这种方式是通用实现方式。下面看第二种实现方式。

2、JOIN_UNIQUE_OUTER/JOIN_UNIQUE_INNER

从SEMI JOIN的语义中,可以看出join过成中,外表一个值仅能匹配内表一个值;这样我们就可以先将内表进行去重,然后再进行普通inner join,从而实现SEMI JOIN。

8018f75394135e043edc2cb88b3e868e.png

先将内表进行去重:可以通过group by进行聚合(hash agg或者sort agg)去重得到内表值;然后针对外表1,顺序扫描内表去重后的值11,不匹配,继续下一个值;下一个值是1,匹配,输出外表值1。针对Join的结果,内表因为去过重,所以满足join条件的必然只有一个值。

3、JOIN_DEDUP_SEMI/JOIN_DEDUP_SEMI_REVERSE

以上两种实现方式是沿用PgSQL,针对的是集中式实现方式。GPDB是分布式,当分布键不匹配时,就需要进行广播MOTION,即使每个segment上去过重,广播MOTION后仍旧可能存在重复值,这样就不能使用第2种实现方式。比如下面案例:第三种实现方式

postgres=# explain select * from s where exists (select 1 from r where s.a = r.b);QUERY PLAN                                                   
---------------------------------------------------------------------------------------------------------------
Gather Motion 3:1  (slice1; segments: 3)  (cost=153.50..155.83 rows=100 width=8)
->  HashAggregate  (cost=153.50..153.83 rows=34 width=8)Group Key: (RowIdExpr)->  Redistribute Motion 3:3  (slice2; segments: 3)  (cost=11.75..153.00 rows=34 width=8)Hash Key: (RowIdExpr)->  Hash Join  (cost=11.75..151.00 rows=34 width=8)Hash Cond: (r.b = s.a)->  Seq Scan on r  (cost=0.00..112.00 rows=3334 width=4)->  Hash  (cost=8.00..8.00 rows=100 width=8)->  Broadcast Motion 3:3  (slice3; segments: 3)  (cost=0.00..8.00 rows=100 width=8)->  Seq Scan on s  (cost=0.00..4.00 rows=34 width=8)
Optimizer: Postgres query optimizer
(12 rows)

分析:

1)上面案例s作为内表,r作为外表。s表远大于r表。s广播motion记录数量众多,代价非常大

2)Hash join构建hash表阶段进行去重

3)外表r不可以广播motion,否则会产生重复值

4)基于上述原因,只能选择广播大表进行JOIN_SEMI了

所以,GPDB实现了第3种方式,即先进行join,然后再去重。主要是为了能够广播小表,比如上述例子种的小表r(作为外表),即使产生重复值也可以在去重阶段去掉。

为了方便去重,GPDB引入了表达式RowIdExpr,即去重操作:DISTINCT ON (RowIdExpr)。该表达式为一条记录产生唯一标识值,附加到该记录中作为一个额外字段。广播后进行join,相对于JOIN_SEMI计划,多了一个重分布MOTION节点,当然MOTION的记录都非常少。上述例子中可以看到hash join后需要在RowIdExpr上进行重分布,然后再在RowIdExpr这个字段上通过Hash Agg进行去重。鉴于hash join前的广播分布和join后的重分布传输的记录数量都比较小,JOIN_DEDUP_SEMI实现方式就在三种实现方式中胜出了。

这篇关于GPDB技术内幕 - SEMI JOIN浅析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/900254

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

java String.join()的使用小结

《javaString.join()的使用小结》String.join()是Java8引入的一个实用方法,用于将多个字符串按照指定分隔符连接成一个字符串,本文主要介绍了javaString.join... 目录1. 方法定义2. 基本用法2.1 拼接多个字符串2.2 拼接集合中的字符串3. 使用场景和示例3

浅析CSS 中z - index属性的作用及在什么情况下会失效

《浅析CSS中z-index属性的作用及在什么情况下会失效》z-index属性用于控制元素的堆叠顺序,值越大,元素越显示在上层,它需要元素具有定位属性(如relative、absolute、fi... 目录1. z-index 属性的作用2. z-index 失效的情况2.1 元素没有定位属性2.2 元素处

浅析Python中的绝对导入与相对导入

《浅析Python中的绝对导入与相对导入》这篇文章主要为大家详细介绍了Python中的绝对导入与相对导入的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1 Imports快速介绍2 import语句的语法2.1 基本使用2.2 导入声明的样式3 绝对import和相对i

浅析如何使用Swagger生成带权限控制的API文档

《浅析如何使用Swagger生成带权限控制的API文档》当涉及到权限控制时,如何生成既安全又详细的API文档就成了一个关键问题,所以这篇文章小编就来和大家好好聊聊如何用Swagger来生成带有... 目录准备工作配置 Swagger权限控制给 API 加上权限注解查看文档注意事项在咱们的开发工作里,API

数据库使用之union、union all、各种join的用法区别解析

《数据库使用之union、unionall、各种join的用法区别解析》:本文主要介绍SQL中的Union和UnionAll的区别,包括去重与否以及使用时的注意事项,还详细解释了Join关键字,... 目录一、Union 和Union All1、区别:2、注意点:3、具体举例二、Join关键字的区别&php

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti