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 ...
随机推荐
- [洛谷P4588][TJOI2018]数学计算
题目大意:有一个数$x$和取模的数$mod$,初始为$1$,有两个操作: $m:x=x\times m$并输出$x\% mod$ $pos:x=x/第pos次操作乘的数$(保证合法),并输出$x\%m ...
- POJ A Simple Problem with Integers | 线段树基础练习
#include<cstdio> #include<algorithm> #include<cstring> typedef long long ll; #defi ...
- PL/SQL 查询结果集直接修改数据
使用t.rowid,查询可以直接在查询结果中修改提交 SELECT t.rowid,t.* from UC_ROLE t where ROLE_NAME like '% %'
- 《c程序设计语言》读书笔记-5.5-指针实现strncpy,strncat,strncmp
#include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> ...
- eclipse增加jar包方式对比
add external jars = 增加工程外部的包add jars = 增加工程内包add library = 增加一个库add class folder = 增加一个类文件夹 add jar ...
- javaScript构造函数、原型、面向对象编程
js最重要也是最核心的东西就是对象了,入行这么长时间,一直对面向对象一知半解.网上有很多介绍对象对象的内容,这里也做了很多借鉴, 尤其是阮一峰老师的文章.我这里写的大多例子都是阮一峰老师文章的例子,但 ...
- i18n(国际化) 和l18n(本地化)时的地域标识代码
i18n(国际化) 和l18n(本地化)时的地域标识代码 格式如 zh-CN(语言-国家) i18n(国际化) 和l18n(本地化)时的地域标识代码 格式如 zh-CN(语言-国家) 国家说明 语言说 ...
- 转: wireshark过滤规则
转: http://blog.sina.com.cn/s/blog_48a0f2740100ka71.html WireShark过滤语法 1.过 滤IP,如来源IP或者目标IP等于某个IP 例子: ...
- OPEN SUSE LINUX
1. 把中文界面变成英文界面 yast2->system->language: 主要语言: 美式英语US 2. 使用root用户默认登录 Ubuntu使用root登录 Ubu ...
- win7 无法启动此程序,因为计算机中丢失glut32.dll
http://zhidao.baidu.com/link?url=9NZxqCvR7hvmKuVR1dUSdQB-TTv_re-g7lp-xZj5FKII04FnMvIKjFhKv299t6wv5Ht ...