Spark(八)【利用广播小表实现join避免Shuffle】
使用场景
大表join小表 只能广播小表
普通的join是会走shuffle过程的,而一旦shuffle,就相当于会将相同key的数据拉取到一个shuffle read task中再进行join,此时就是reduce join。但是如果一个RDD是比较小的,则可以采用广播小RDD全量数据+map算子来实现与join同样的效果,也就是map join,此时就不会发生shuffle操作,也就不会发生数据倾斜。
注意:RDD是并不能进行广播的,只能将RDD内部的数据通过collect拉取到Driver内存然后再进行广播
核心思路
 将较小RDD中的数据直接通过collect算子拉取到Driver端的内存中来,然后对其创建一个Broadcast变量;接着对另外一个RDD执行map类算子,在算子函数内,从Broadcast变量中获取较小RDD的全量数据,与当前RDD的每一条数据按照连接key进行比对,如果连接key相同的话,那么就将两个RDD的数据用你需要的方式连接起来。
代码演示
正常join
    val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("MapJoin")
    val sc: SparkContext = new SparkContext(conf)
    val rdd1: RDD[(String, Int)] = sc.makeRDD(List("key1" -> 2, "key1" -> 10, "key2" -> 20, "key3" -> 30))
    val rdd2: RDD[(String, Int)] = sc.makeRDD(List("key1" -> 5, "key1" -> 20, "key2" -> 40, "key4" -> 30))
	 //join
    rdd1.join(rdd2).collect().foreach(println)
控制台
(key1,(2,5))
(key1,(2,20))
(key1,(10,5))
(key1,(10,20))
(key2,(20,40))
正常left join
//left join
rdd1.leftOuterJoin(rdd2).collect().foreach(println)
(k1,(10,Some(-10)))
(k1,(10,Some(-100)))
(k2,(20,Some(-20)))
(k1,(100,Some(-10)))
(k1,(100,Some(-100)))
(k3,(30,None))
广播:join
    //广播rdd2
    val bd: Broadcast[Array[(String, Int)]] = sc.broadcast(rdd2.collect())
    val result = rdd1.flatMap {
      case (key1, value1) => {
        bd.value
          .filter(key1 == _._1)
          .map {
            case (key2, value2) =>
              (key1, (value1, value2))
          }
      }
    }
    result.collect().foreach(println)
广播:left join
    //广播rdd2
    val bd: Broadcast[Array[(String, Int)]] = sc.broadcast(rdd2.collect())
    val result: RDD[(String, (Int, Option[Int]))] = rdd1.flatMap {
      case (key1, value1) =>
        val arr = bd.value
        val keys = arr.map(_._1)
        if (keys.contains(key1)) {
          bd.value.filter(key1 == _._1).map {
            case (key2, value2) =>
              (key1, (value1, Some(value2)))
          }
        } else {
          Array(key1 -> (value1, None))
        }
    }
    result.collect.foreach(println)
不适用场景
由于Spark的广播变量是在每个Executor中保存一个副本,如果两个RDD数据量都比较大,那么如果将一个数据量比较大的 RDD做成广播变量,那么很有可能会造成内存溢出。
Spark(八)【利用广播小表实现join避免Shuffle】的更多相关文章
- Spark(八)【广播变量和累加器】
		目录 一. 广播变量 使用 二. 累加器 使用 使用场景 自定义累加器 在spark程序中,当一个传递给Spark操作(例如map和reduce)的函数在远程节点上面运行时,Spark操作实际上操作的 ... 
- 【Spark调优】小表join大表数据倾斜解决方案
		[使用场景] 对RDD使用join类操作,或者是在Spark SQL中使用join语句时,而且join操作中的一个RDD或表的数据量比较小(例如几百MB或者1~2GB),比较适用此方案. [解决方案] ... 
- 【Spark调优】大表join大表,少数key导致数据倾斜解决方案
		[使用场景] 两个RDD进行join的时候,如果数据量都比较大,那么此时可以sample看下两个RDD中的key分布情况.如果出现数据倾斜,是因为其中某一个RDD中的少数几个key的数据量过大,而另一 ... 
- SQL Join连接大小表在前在后的重要性(小表在前提高执行效率)
		引用地址:https://blog.csdn.net/qq_30349961/article/details/82662550 http://blog.sina.com.cn/s/blog_6ff05 ... 
- Hive中小表与大表关联(join)的性能分析【转】
		Hive中小表与大表关联(join)的性能分析 [转自:http://blog.sina.com.cn/s/blog_6ff05a2c01016j7n.html] 经常看到一些Hive优化的建议中说当 ... 
- 并行HASH JOIN小表广播问题
		SQL语句: SELECT /*+parallel(t1 16)*/ T1.DATA_DATE, T1.ACCT_NO, T1.ACCT_ORD, T1.ACCT_NO_PK, T1.ACCT_BAL ... 
- OLAP 大表和小表并行hash join
		一个表50MB 一个表10GB 50M表做驱动表,放在PGA里 这时候慢在对对 10g 的全表扫描 对10个G扫描块 需要开并行 我有这样一个算法 一个进程 读 50mb 8进程 来 扫描 10gb ... 
- 大数据开发实战:Hive优化实战2-大表join小表优化
		4.大表join小表优化 和join相关的优化主要分为mapjoin可以解决的优化(即大表join小表)和mapjoin无法解决的优化(即大表join大表),前者相对容易解决,后者较难,比较麻烦. 首 ... 
- Mysql优化原则_小表驱动大表IN和EXISTS的合理利用
		//假设一个for循环 ; $i < ; $i++) { ; $i < ; $j++) { } } ; $i < ; $i++) { ; $i < ; $j++) { } } ... 
随机推荐
- linux updatedb: can not open a temporary file for `/var/lib/mlocate/mlocate.db'
			我们想查找我们最新创建的文件时,由于locate的数据库是每天更新.所以我们新创建的文件还没有被更新到系统的数据库. 这是需要手动更新数据库. 然后就可以查到. updatedb 输出 updated ... 
- reorder-list leetcode C++
			Given a singly linked list L: L 0→L 1→-→L n-1→L n, reorder it to: L 0→L n →L 1→L n-1→L 2→L n-2→- You ... 
- eclipse javaEE版下载过程中选择镜像(Select Another Mirror)无反应解决办法,附带eclipse javaEE版下载教程。
			1.eclipse javaEE版下载过程中选择镜像(Select Another Mirror)无反应 (复制该网址下载即可 https://mirrors.neusoft.edu.cn/eclip ... 
- SpringCloud微服务实战——搭建企业级开发框架(十三):OpenFeign+Ribbon实现高可用重试机制
			Spring Cloud OpenFeign 默认是使用Ribbon实现负载均衡和重试机制的,虽然Feign有自己的重试机制,但该功能在Spring Cloud OpenFeign基本用不上,除非 ... 
- 负载均衡算法WRR介绍
			一.负载均衡 负载均衡是一个很大的概念,既有从硬件层面来解决问题的,又有从软件层面解决的,有关负载均衡的介绍,推荐阅读: http://os.51cto.com/art/201108/285359.h ... 
- C++ pragma once 与 ifndef 用法区别
			#pragma once 与 #ifndef 的作用 (1)在C/C++中,在使用预编译指令#include的时候,为了防止重复引用造成二义性. (2)在能够支持这两种方式的编译器上,二者并没有太大的 ... 
- uni-app路径规划(打开第三方地图实现)
			百度网盘链接:https://pan.baidu.com/s/1-Ys13GFcnKXB1wkJotcwMw 提取码:16gp 把js文件放在common目录下 引入: import pathP ... 
- Windows内核中的CPU架构-7-陷阱门(32-Bit Trap Gate)
			Windows内核中的CPU架构-7-陷阱门(32-Bit Trap Gate) 陷阱门和中断门几乎是一模一样的: (注:图里高32位中的第11位的值为D,其实是1) 除了高32位中的type字段的内 ... 
- Python基础(列表生成式)
			import os; list1 = list(range(1,11)) list2 = [x*x for x in list1 if x % 2 == 0]#列表生成式时,把要生成的元素x * x放 ... 
- SCTL 涅槃重生:投入 RAL 的怀抱
			在<DistSQL:像数据库一样使用 Apache ShardingSphere>一文中,PMC 孟浩然为大家介绍了 DistSQL 的设计初衷和语法体系,并通过实战操作展示了一条 SQL ... 
