北京企业网站建设费用关于美食的网站设计
北京企业网站建设费用,关于美食的网站设计,商标设计大全,创可贴在线设计平台文章目录前言#xff1a;Join背景介绍Join常见分类以及基本实现机制Hash JoinBroadcast Hash JoinShuffle Hash JoinSort-Merge Join总结前言#xff1a;
写SQL的时候很多时候都有用到join语句#xff0c;但是我们真的有仔细想过数据在join的过程到底是怎么样的吗#xff…
文章目录前言Join背景介绍Join常见分类以及基本实现机制Hash JoinBroadcast Hash JoinShuffle Hash JoinSort-Merge Join总结前言
写SQL的时候很多时候都有用到join语句但是我们真的有仔细想过数据在join的过程到底是怎么样的吗今天借这位大神的文章来交接下sql中join的原理。同样如有冒犯请联系。
Join背景介绍
Join是数据库查询永远绕不开的话题传统查询SQL技术总体可以分为简单操作过滤操作-where、排序操作-limit等聚合操作-groupBy等以及Join操作等。其中Join操作是其中最复杂、代价最大的操作类型也是OLAP场景中使用相对较多的操作。因此很有必要聊聊这个话题。 另外从业务层面来讲用户在数仓建设的时候也会涉及Join使用的问题。通常情况下数据仓库中的表一般会分为”低层次表”和“高层次表”。 所谓”低层次表”就是数据源导入数仓之后直接生成的表单表列值较少一般可以明显归为维度表或者事实表表和表之间大多存在外健依赖所以查询起来会遇到大量Join运算查询效率相对比较差。而“高层次表”是在”低层次表”的基础上加工转换而来通常做法是使用SQL语句将需要Join的表预先进行合并形成“宽表”在宽表上的查询因为不需要执行大量Join因而效率相对较高很明显宽表缺点是数据会有大量冗余而且生成相对比较滞后查询结果可能并不及时。 因此为了获得实效性更高的查询结果大多数场景还是需要进行复杂的Join操作。Join操作之所以复杂不仅仅因为通常情况下其时间空间复杂度高更重要的是它有很多算法在不同场景下需要选择特定算法才能获得最好的优化效果。关系型数据库也有关于Join的各种用法姜承尧大神之前由浅入深地介绍过MySQL Join的各种算法以及调优方案关注公众号InsideMySQL并回复join可以查看相关文章。本文接下来会介绍SparkSQL所支持的几种常见的Join算法以及其适用场景。
Join常见分类以及基本实现机制
**当前SparkSQL支持三种Join算法shuffle hash join、broadcast hash join以及sort merge join。**其中前两者归根到底都属于hash join只不过在hash join之前需要先shuffle还是先broadcast。其实这些算法并不是什么新鲜玩意都是数据库几十年前的老古董了参考只不过换上了分布式的皮而已。不过话说回来SparkSQL/Hive…等等所有这些大数据技术哪一样不是来自于传统数据库技术什么语法解析AST、基于规则优化CRO、基于代价优化CBO、列存都来自于传统数据库。就拿shuffle hash join和broadcast hash join来说hash join算法就来自于传统数据库而shuffle和broadcast是大数据的皮两者一结合就成了大数据的算法了。因此可以这样说大数据的根就是传统数据库传统数据库人才可以很快的转型到大数据。好吧这些都是闲篇。 继续来看技术既然hash join是’内核’那就刨出来看看看完把’皮’再分析一下。
Hash Join
先来看看这样一条SQL语句
select * from order,item where item.id order.i_id很简单一个Join节点参与join的两张表是item和orderjoin key分别是item.id以及order.i_id。现在假设这个Join采用的是hash join算法整个过程会经历三步 1、 确定Build Table以及Probe Table这个概念比较重要Build Table使用join key构建Hash Table而Probe Table使用join key进行探测探测成功就可以join在一起。通常情况下小表会作为Build Table大表作为Probe Table。此事例中item为Build Tableorder为Probe Table。 2、 构建Hash Table依次读取Build Tableitem的数据对于每一行数据根据join keyitem.id进行hashhash到对应的Bucket生成hash table中的一条记录。数据缓存在内存中如果内存放不下需要dump到外存。这里是先利用join key hash到对应的bucket中然后利用相同的hash规则去连接另一张表中相同的key数据 3、探测再依次扫描Probe Tableorder的数据使用相同的hash函数映射Hash Table中的记录映射成功之后再检查join条件item.id order.i_id如果匹配成功就可以将两者join在一起。 总结 确定小表为build table,大表为probe table之后利用小表的join key构建hash table。扫描小表全表不同的join key被分发到不同的bucket下之后再依次扫描probe table按照同样的hash规则将数据hash到不同的bucket下之后在bucket下扫描小表数据若join条件一致则可将两者join在一起。 基本流程可以参考上图这里有两个小问题需要关注 1、 hash join性能如何很显然hash join基本都只扫描两表一次可以认为o(ab)较之最极端的笛卡尔集运算a*b不知甩了多少条街。 2、为什么Build Table选择小表道理很简单因为构建的Hash Table最好能全部加载在内存效率最高这也决定了hash join算法只适合至少一个小表的join场景对于两个大表的join场景并不适用 上文说过hash join是传统数据库中的单机join算法在分布式环境下需要经过一定的分布式改造说到底就是尽可能利用分布式计算资源进行并行化计算提高总体效率。hash join分布式改造一般有两种经典方案 1、broadcast hash join将其中一张小表广播分发到另一张大表所在的分区节点上分别并发地与其上的分区记录进行hash join。broadcast适用于小表很小可以直接广播的场景。 2、shuffler hash join 一旦小表数据量较大此时就不再适合进行广播分发。这种情况下可以根据join key相同必然分区相同的原理将两张表分别按照join key进行重新组织分区这样就可以将join分而治之划分为很多小join充分利用集群资源并行化。相当于在map端将大小按照key进行拆分重新组织分区然后根据key分发到reduce端进行分别大小表的处理最终再将结果进行汇总。
Broadcast Hash Join
如下图所示broadcast hash join可以分为两步 1、broadcast阶段将小表广播分发到大表所在的所有主机。广播算法可以有很多最简单的是先发给driverdriver再统一分发给所有executor要不就是基于bittorrete的p2p思路 基于bittorrete的p2p思路可参考 https://zhidao.baidu.com/question/9782615.html https://baike.baidu.com/item/BitTorrent/142795?fraladdin 2、hash join阶段在每个executor上执行单机版hash join小表映射大表试探 SparkSQL规定broadcast hash join执行的基本条件为被广播小表必须小于参数spark.sql.autoBroadcastJoinThreshold默认为10M。
Shuffle Hash Join
在大数据条件下如果一张表很小执行join操作最优的选择无疑是broadcast hash join效率最高。但是一旦小表数据量增大广播所需内存、带宽等资源必然就会太大broadcast hash join就不再是最优方案。此时可以按照join key进行分区根据key相同必然分区相同的原理就可以将大表join分而治之划分为很多小表的join充分利用集群资源并行化。如下图所示shuffle hash join也可以分为两步 1、shuffle阶段分别将两个表按照join key进行分区将相同join key的记录重分布到同一节点两张表的数据会被重分布到集群中所有节点。这个过程称为shuffle 2、hash join阶段每个分区节点上的数据单独执行单机hash join算法。最后应该还要做一个union all的操作将之前处理的内容进行合并 看到这里**可以初步总结出来如果两张小表join可以直接使用单机版hash join如果一张大表join一张极小表可以选择broadcast hash join算法**而如果是一张大表join一张小表则可以选择shuffle hash join算法那如果是两张大表进行join呢
Sort-Merge Join
SparkSQL对两张大表join采用了全新的算法sort-merge join如下图所示整个过程分为三个步骤 1、shuffle阶段将两张大表根据join key进行重新分区两张表数据会分布到整个集群以便分布式并行处理 2、sort阶段对单个分区节点的两表数据分别进行排序 3、merge阶段对排好序的两张分区表数据执行join操作。join操作很简单分别遍历两个有序序列碰到相同join key就merge输出否则取更小一边两张分区表进行join的过程中会不断的比较索引的大小一直以索较小的索引值遍历分区表数据。见下图示意 仔细分析的话会发现sort-merge join的代价并不比shuffle hash join小反而是多了很多。那为什么SparkSQL还会在两张大表的场景下选择使用sort-merge join算法呢这和Spark的shuffle实现有关目前spark的shuffle实现都适用sort-based shuffle算法因此在经过shuffle之后partition数据都是按照key排序的。因此理论上可以认为数据经过shuffle之后是不需要sort的可以直接merge也就是说sort-merge-join实际只需要执行shuffle和merge阶段而shuffle-hash-join需要执行shuffle和hash-join阶段。而对于大表join大表来说merge阶段比hash-join阶段更优 为什么更优hash-join的复杂度O(ab)而merge小于O(ab)。a,b代表数组的长度。 经过上文的分析可以明确每种Join算法都有自己的适用场景数据仓库设计时最好避免大表与大表的join查询SparkSQL也可以根据内存资源、带宽资源适量将参数spark.sql.autoBroadcastJoinThreshold调大让更多join实际执行为broadcast hash join。
总结
Join操作是传统数据库中的一个高级特性尤其对于当前MySQL数据库更是如此原因很简单MySQL对Join的支持目前还比较有限只支持Nested-Loop Join算法因此在OLAP场景下MySQL是很难吃的消的不要去用MySQL去跑任何OLAP业务结果真的很难看。不过好消息是MySQL在新版本要开始支持Hash Join了这样也许在将来也可以用MySQL来处理一些小规模的OLAP业务。 和MySQL相比PostgreSQL、SQLServer、Oracle等这些数据库对Join支持更加全面一些都支持Hash Join算法。由PostgreSQL作为内核构建的分布式系统Greenplum更是在数据仓库中占有一席之地这和PostgreSQL对Join算法的支持其实有很大关系。 总体而言传统数据库单机模式做Join的场景毕竟有限也建议尽量减少使用Join。然而大数据领域就完全不同Join是标配OLAP业务根本无法离开表与表之间的关联对Join的支持成熟度一定程度上决定了系统的性能夸张点说’得Join者得天下’。本文只是试图带大家真正走进Join的世界了解常用的几种Join算法以及各自的适用场景。
参考http://hbasefly.com/2017/03/19/sparksql-basic-join/
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/91756.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!