Spark map-side-join 关联优化
在spark中要进行join操作,如果在shuffle的时候进行join效率较低。如果满足 所需要join的表中有一张表较小,那么可以考虑在map端进行join操作。
转载:http://blog.csdn.net/lsshlsw/article/details/50834858
将多份数据进行关联是数据处理过程中非常普遍的用法,不过在分布式计算系统中,这个问题往往会变的非常麻烦,因为框架提供的 join 操作一般会将所有数据根据 key 发送到所有的 reduce 分区中去,也就是 shuffle 的过程。造成大量的网络以及磁盘IO消耗,运行效率极其低下,这个过程一般被称为 reduce-side-join。
如果其中有张表较小的话,我们则可以自己实现在 map 端实现数据关联,跳过大量数据进行 shuffle 的过程,运行时间得到大量缩短,根据不同数据可能会有几倍到数十倍的性能提升。
下文将会以一个 demo 进行说明。
何时使用
在海量数据中匹配少量特定数据
原理
以前写过一篇关于spark-sql中利用broadcast join进行优化的文章,原理与那篇文章相同,这里重新画了图。
http://blog.csdn.net/lsshlsw/article/details/48694893
reduce-side-join 的缺陷在于会将key相同的数据发送到同一个partition中进行运算,大数据集的传输需要长时间的IO,同时任务并发度收到限制,还可能造成数据倾斜。
reduce-side-join 运行图如下
map-side-join 运行图如下
代码说明
数据1(个别人口信息):
身份证 姓名 ...
lsw
yyy
数据2(全国学生信息):
身份证 学校名称 学号 ...
s1
s2
s3
s2
期望得到的数据 :
身份证 姓名 学校名称
lsw s1
将少量的数据转化为Map进行广播,广播会将此 Map 发送到每个节点中,如果不进行广播,每个task执行时都会去获取该Map数据,造成了性能浪费。
val people_info = sc.parallelize(Array(("","lsw"),("","yyy"))).collectAsMap()
val people_bc = sc.broadcast(people_info)
对大数据进行遍历,使用mapPartition而不是map,因为mapPartition是在每个partition中进行操作,因此可以减少遍历时新建broadCastMap.value对象的空间消耗,同时匹配不到的数据也不会返回()。
val res = student_all.mapPartitions(iter =>{
val stuMap = people_bc.value
val arrayBuffer = ArrayBuffer[(String,String,String)]()
iter.foreach{case (idCard,school,sno) =>{
if(stuMap.contains(idCard)){
arrayBuffer.+= ((idCard, stuMap.getOrElse(idCard,""),school))
}
}}
arrayBuffer.iterator
})
也可以使用 for 的守卫机制来实现上述代码
val res1 = student_all.mapPartitions(iter => {
val stuMap = people_bc.value
for{
(idCard, school, sno) <- iter
if(stuMap.contains(idCard))
} yield (idCard, stuMap.getOrElse(idCard,""),school)
})
完整代码
import org.apache.spark.{SparkContext, SparkConf}
import scala.collection.mutable.ArrayBuffer
object joinTest extends App{
val conf = new SparkConf().setMaster("local[2]").setAppName("test")
val sc = new SparkContext(conf)
/**
* map-side-join
* 取出小表中出现的用户与大表关联后取出所需要的信息
* */
//部分人信息(身份证,姓名)
val people_info = sc.parallelize(Array(("","lsw"),("","yyy"))).collectAsMap()
//全国的学生详细信息(身份证,学校名称,学号...)
val student_all = sc.parallelize(Array(("","s1",""),
("","s2",""),
("","s3",""),
("","s2","")))
//将需要关联的小表进行关联
val people_bc = sc.broadcast(people_info)
/**
* 使用mapPartition而不是用map,减少创建broadCastMap.value的空间消耗
* 同时匹配不到的数据也不需要返回()
* */
val res = student_all.mapPartitions(iter =>{
val stuMap = people_bc.value
val arrayBuffer = ArrayBuffer[(String,String,String)]()
iter.foreach{case (idCard,school,sno) =>{
if(stuMap.contains(idCard)){
arrayBuffer.+= ((idCard, stuMap.getOrElse(idCard,""),school))
}
}}
arrayBuffer.iterator
})
/**
* 使用另一种方式实现
* 使用for的守卫
* */
val res1 = student_all.mapPartitions(iter => {
val stuMap = people_bc.value
for{
(idCard, school, sno) <- iter
if(stuMap.contains(idCard))
} yield (idCard, stuMap.getOrElse(idCard,""),school)
})
res.foreach(println)
Spark map-side-join 关联优化的更多相关文章
- hadoop 多表join:Map side join及Reduce side join范例
最近在准备抽取数据的工作.有一个id集合200多M,要从另一个500GB的数据集合中抽取出所有id集合中包含的数据集.id数据集合中每一个行就是一个id的字符串(Reduce side join要在每 ...
- Spark 中的join方式(pySpark)
spark基础知识请参考spark官网:http://spark.apache.org/docs/1.2.1/quick-start.html 无论是mapreduce还是spark ,分布式框架的性 ...
- Spark SQL 之 Join 实现
原文地址:Spark SQL 之 Join 实现 Spark SQL 之 Join 实现 涂小刚 2017-07-19 217标签: spark , 数据库 Join作为SQL中一个重要语法特性,几乎 ...
- Spark调优,性能优化
Spark调优,性能优化 1.使用reduceByKey/aggregateByKey替代groupByKey 2.使用mapPartitions替代普通map 3.使用foreachPartitio ...
- hadoop的压缩解压缩,reduce端join,map端join
hadoop的压缩解压缩 hadoop对于常见的几种压缩算法对于我们的mapreduce都是内置支持,不需要我们关心.经过map之后,数据会产生输出经过shuffle,这个时候的shuffle过程特别 ...
- 【MySQL】查询优化实例解析-延迟关联优化
[提出问题] 从数据表t通过分页查询的方式读取数据,读取时要根据a1排序.t有80万行记录,当OFFSET很大时,读取速度很慢.优化后查询速度提升很快. 下图是表的定义,一共有几十个字段,RowLen ...
- Spark访问与HBase关联的Hive表
知识点1:创建关联Hbase的Hive表 知识点2:Spark访问Hive 知识点3:Spark访问与Hbase关联的Hive表 知识点1:创建关联Hbase的Hive表 两种方式创建,内部表和外部表 ...
- MySQL 分页查询优化——延迟关联优化
目录 1. InnoDB表的索引的几个概念 2. 覆盖索引和回表 3. 分页查询 4. 延迟关联优化 写在前面 下面的介绍均是在选用MySQL数据库和Innodb引擎的基础开展.我们先 ...
- MapReduce Join关联
Reduce join 原理 Map端的主要工作:为来自不同表(文件)的key/value对打标签以区别不同来源的记录.然后用连接字段作为key,其余部分和新加的标志作为value,最后进行输出. R ...
随机推荐
- 测试计划驱动开发模式 TPDD:一种比 TDD 更友好的开发模式
相信大部分开发团队都在使用TDD,并且还有很多开发团队都 对外声明 在使用 TDD 开发模式. 之所以说是“对外声明”,是因为很多开发团队虽然号称使用的是 TDD 开发模式,实际开发过程中却无法满足 ...
- 2017-7-18-每日博客-关于Linux下的通配符.doc
*:匹配零个或多个字符 ?:匹配任意单个字符 ~:当前用户家目录 ~username:用户家目录 ~+:当前工作目录 ~-:上一个工作目录 [0-9]:匹配任意数字范围 [a-z]:匹配任意小写字母( ...
- AtCoder Regular Contest 093 E: Bichrome Spanning Tree(生成树)
Bichrome Spanning Tree 题意: 给出一个n个点,m条边的无向连通图,现在要给每条边染色,可以染成黑色或者白色. 现在要求在染色完毕后,找出一个至少包含一条黑边和一条白边的最小生成 ...
- eclipse搭建ssm框架的maven的工程
版本:eclipse:Indigo Service Release 2. jdk :jdk1.7.0_03. maven:apache-maven-3.3.3 . 上面的3个东西 先下载下来.然后运 ...
- WCF技术剖析 Two
WCF终结点和寻址之--AddressHead信息匹配代码 Contracts契约 using System; using System.Collections.Generic; using Syst ...
- 大(NOIP模拟赛Round #10)
题目描述: 小Z有个n个点的高清大图,每个点有且只有一条单向边的出边.现在你可以翻转其中的一些边,使他从任何一个点都不能通过一些道路走回这个点.为了方便,你只需输出方案数对取模即可.当在两个方案中有任 ...
- mininet命令
官方文档:http://mininet.org/walkthrough/ 翻译的官方文档:https://segmentfault.com/a/1190000000669218 ovs-ofctl相关 ...
- JS打印——第三方控件打印
LODOP 官方地址:http://www.lodop.net/ 一个很好的打印控件,可以是实现纸张设置.横打竖打.打印预览.打印维护多种功能.官网的示例非常详细.能很好支持多种浏览器的打印. 在使用 ...
- python接口自动化4-绕过验证码登录(cookie)【转载】
本篇转自博客:上海-悠悠 原文地址:http://www.cnblogs.com/yoyoketang/tag/python%E6%8E%A5%E5%8F%A3%E8%87%AA%E5%8A%A8%E ...
- 同样的promise,调用方法不一样,执行顺序不一样
在测试两个不同的代码时发现的. 其实也理解,一个是新建一个空的promise,另一个是新建的promise马上执行,去分支resolve状态, 当然就空的在后. <script> //se ...