sparksql的3种join实现

1、Broadcast Join (小表对大表)

在数据库的常见模型中(比如星型模型或者雪花模型),表一般分为两种:事实表和维度表。

维度表一般指固定的、变动较少的表,例如联系人、物品种类等,一般数据有限。

事实表一般记录流水,比如销售清单等,通常随着时间的增长不断膨胀。

因为Join 操作是对两个表中key值相同的记录进行连接,在SparkSQL中,对两个表做join最直接的方式是先根据key分区,再在每个分区中把key值相同的记录拿出来做

连接操作。但这样就不可避免地涉及到shuffle,而shuffle在spark中比较耗时的操作,我们应该尽可能的设计Spark应用使其避免大量的shuffle。

当维度表和事实表进行join操作时,为了避免shuffle,我们可以将大小有限的维度表的全部数据分发到每个节点上,供事实表使用。executor存储维度表的全部数据,一定程度上牺牲了

空间,换取shuffle操作大量的耗时,这在SparkSQL中称作 Broadcast Join。

Table B 是较小的表,黑色表示将其广播到每个executor节点上,Table A 的每个partition 会通过 block manager取到Table A的数据。根据每条记录的 Join Key 取到

Table B中相对应的记录,根据 Join Type进行操作。这个过程比较简单,不做赘述。

ps:禁用广播命令:  set spark.sql.autoBroadcastJoinThreshold=-1;

Broadcast Join 的条件有以下几个:

(1)被广播的表需要小于 spark.sql.autoBroadcastJoinThreshold所配置的值,默认是10M(或者加了 broadcast join的 hint)

(2)基表不能被广播,比如 left outer join时,只能广播右表。

看起来广播是一个比较理想的方案,但它有没有缺点呢?也很明显。这个方案只能用于广播较小的表,否则数据的冗余传输就远大于shuffle的开销;

另外,广播时需要将被广播的表collect 到driver端,然后由driver端将数据分发到其他executor,当频繁有广播出现时,对driver的内存也是一个考验。

2、Shuffle Hash Join

当一侧的表比较小时,我们选择将其广播出去以避免shuffle,提高性能。但因为被广播的表首先被collect到driver端,然后被冗余分发到每个executor上,所以当表比较大时,

采用 broadcast join 会对driver端和executor端造成较大的压力。

但由于Spark 是一个分布式的计算引擎,可以通过分区的形式将大批量的数据划分成n份较小的数据集进行并行计算。这种思想应用到Join上便是 Shuffle Hash Join 了。

利用key相同必然分区相同的这个原理,Spark SQL将较大表的 join 分而治之,先将表划分成 n 个分区,再对两个表中相对应分区的数据分别进行 Hash Join,这样即在

一定程度上减少了driver广播一侧表的压力,也减少了executor端取整张被广播表的内存消耗。

Shuffle Hash Join 分为两步:
1、对两张表分别按照 join keys进行重分区,即shuffle,目的就是为了让有相同 join  keys值的记录分到对应的分区中。

2、对对应分区中的数据进行 join,此处先将小表分区构造为一张hash 表,然后根据大表分区中记录的join keys值拿出来进行匹配。

Shuffle Hash Join 的条件有以下几个:

1、分区的平均大小不超过 spark.sql.autoBroadcastJoinThreshold 所配置的值,默认是 10M。

2、基表不能被广播,比如 left outer join 时,只能广播右表。

3、一侧的表要明显小于另外一侧,小的一侧将被广播(明显小于的定义为3倍小)

我们可以看到,在一定大小的表中,SparkSQL从时空结合的角度来看,将两个表进行重新分区,并且对小表中的分区进行hash化,从而完成join。

在保持一定复杂度的基础上,尽量减少driver和executor的内存压力,提升了计算时的稳定性。

Sort Merge Join (大表对大表)

上面介绍的两种实现对于一定大小的表表适用,但当两个表都非常大时,显然无论用哪种都会对计算内存造成很大压力。这是因为join 时两者采取的都是 hash join,

是将一侧的数据完全加载到内存中,使用 hash code取 join keys值相等的记录进行连接。

当两个表都非常大时,SparkSQL 采用了一种全新的方案来对标进行 join,即 Sort Merge Join 。这种实现方式不用将一侧数据全部加载后再进行 hash join,但需要在

join 前将数据排序。

可以看到,首先将两张表按照 join keys 进行了重新shuffle,保证 join keys值相同的记录会被分在相应的分区。分区后对每个分区内的数据进行排序,排序后

再对相应的分区内的记录进行连接。

因为两个序列都是有序的,从头遍历,碰到 key 相同的就输出,如果不同,左边小就继续取左边,反之取右边。

可以看出,无论分区有多大,Sort Merge Join 都不用把某一侧的数据全部加载到内存中,而是即用即丢,从而大大提升了大数量下 sql join 的稳定性。

sparksql的join有哪些及实现原理的更多相关文章

  1. hive------ Group by、join、distinct等实现原理

    1. Hive 的 distribute by Order by 能够预期产生完全排序的结果,但是它是通过只用一个reduce来做到这点的.所以对于大规模的数据集它的效率非常低.在很多情况下,并不需要 ...

  2. ☕【Java技术指南】「并发编程专题」Fork/Join框架基本使用和原理探究(基础篇)

    前提概述 Java 7开始引入了一种新的Fork/Join线程池,它可以执行一种特殊的任务:把一个大任务拆成多个小任务并行执行. 我们举个例子:如果要计算一个超大数组的和,最简单的做法是用一个循环在一 ...

  3. SparkSQL大数据实战:揭开Join的神秘面纱

    本文来自 网易云社区 . Join操作是数据库和大数据计算中的高级特性,大多数场景都需要进行复杂的Join操作,本文从原理层面介绍了SparkSQL支持的常见Join算法及其适用场景. Join背景介 ...

  4. Nested loops、Hash join、Sort merge join(三种连接类型原理、使用要点)

    nested loop 嵌套循环(原理):oracle从较小结果集(驱动表.也可以被称为outer)中读取一行,然后和较大结果集(被侦查表,也可以叫做inner)中的所有数据逐条进行比较(也是等值连接 ...

  5. 面试官: Flink双流JOIN了解吗? 简单说说其实现原理

    摘要:今天和大家聊聊Flink双流Join问题.这是一个高频面试点,也是工作中常遇到的一种真实场景. 本文分享自华为云社区<万字直通面试:Flink双流JOIN>,作者:大数据兵工厂 . ...

  6. 从Search Sort到Join

    发表于<程序员>2015年4月B的一篇文章,在博客归档下.根据杂志社要求,在自己博客发表该文章亦须注明:本文为CSDN编译整理,未经允许不得转载,如需转载请联系market#csdn.ne ...

  7. sparkSQL实战详解

    摘要   如果要想真正的掌握sparkSQL编程,首先要对sparkSQL的整体框架以及sparkSQL到底能帮助我们解决什么问题有一个整体的认识,然后就是对各个层级关系有一个清晰的认识后,才能真正的 ...

  8. sparkSQL整体实现框架

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://9269309.blog.51cto.com/9259309/1845525 这篇 ...

  9. Golang 源码解读 01、深入解析 strings.Builder、strings.Join

    strings.Builder 源码解析. 存在意义. 实现原理. 常用方法. 写入方法. 扩容方法. String() 方法. 禁止复制. 线程不安全. io.Writer 接口. 代码. stri ...

  10. 大数据篇:Spark

    大数据篇:Spark Spark是什么 Spark是一个快速(基于内存),通用,可扩展的计算引擎,采用Scala语言编写.2009年诞生于UC Berkeley(加州大学伯克利分校,CAL的AMP实验 ...

随机推荐

  1. (四)elasticsearch 源码之索引流程分析

    1.概览 前面我们讨论了es是如何启动,本文研究下es是如何索引文档的. 下面是启动流程图,我们按照流程图的顺序依次描述.     其中主要类的关系如下:     2. 索引流程 我们用postman ...

  2. 发布了一个jar包到中央仓库,我的心好累…

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 哈喽大家好啊,我是Hydra. 前几天我在网上冲浪的时候,看见有一个老铁在git上给我提了一个issue: 万万没想到,有一天我写的烂代码居然也 ...

  3. 光速上手k8s(2023)(containerd)(未完待续)

    又过了好久没写了,主要是近来状况也无聊 一.了解概念(参考) 概念 Kubernetes 是一个可移植.可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化. Kubernete ...

  4. 如何在mac电脑上配置命令行工具

    Hi,欢迎大家在有空的时候做客[江涛学编程],这里是2023年的第7篇原创文章,今天我们来聊一聊如何在mac电脑上配置命令行工具 老规矩,拍拍手,上菜. 同学,打开你的mac电脑,按住键盘上的&quo ...

  5. 炫酷科技感黑客感瀑布流html代码

    效果如下 代码如下 <!DOCTYPE html><html> <head> <meta http-equiv="Content-Type" ...

  6. 在Spring Boot中整合Katharsis,来快速开发JSON API的Web应用

    1 简介 我们进行Web API开发的时候,经常会使用Json格式的消息体,而Json格式非常灵活,不同的人会有不同的设计风格和实现,而JSON API提供了一套标准.但它并不提供直接实现. Kath ...

  7. java基础:方法

    方法 方法是解决一类问题的步骤的有序组合 包含于类/对象中 设计原则 方法的原子性:一个方法只实现一个功能 定义与调用 方法的组成: 方法的调用 若方法返回值为空 System.out.println ...

  8. 浅谈Pytest中的warning处理

    浅谈Pytest中的warning处理 没有处理warning 我们写一个简单的测试 import pytest def test_demo(): import warnings warnings.w ...

  9. python学习第六周总结

    封装 封装:就是将数据和功能'封装'起来 隐藏:在类的定义阶段名字前面使用两个下划线表示隐藏.就是将数据和功能隐藏起来不让用户直接调用,而是开发一些接口间接调用,从而可以在接口内添加额外的操作 伪装: ...

  10. P7_小程序的宿主环境

    宿主环境简介 什么是宿主环境 宿主环境(host environment)指的是程序运行所必须的依赖环境.例如:Android 系统和 iOS 系统是两个不同的宿主环境.安卓版的微信 App 是不能在 ...