实现Map-side Join和Reduce-side Join(转)
在大数据处理场景中,多表Join是非常常见的一类运算。为了便于求解,通常会将多表join问题转为多个两表连接问题。两表Join的实现算法非常多,一般我们会根据两表的数据特点选取不同的join算法,其中,最常用的两个算法是map-side join和reduce-side join。本文将介绍如何在apache spark中实现这两种算法。
(1)Map-side Join
Map-side Join使用场景是一个大表和一个小表的连接操作,其中,“小表”是指文件足够小,可以加载到内存中。该算法可以将join算子执行在Map端,无需经历shuffle和reduce等阶段,因此效率非常高。
在Hadoop MapReduce中, map-side join是借助DistributedCache实现的。DistributedCache可以帮我们将小文件分发到各个节点的Task工作目录下,这样,我们只需在程序中将文件加载到内存中(比如保存到Map数据结构中),然后借助Mapper的迭代机制,遍历另一个大表中的每一条记录,并查找是否在小表中,如果在则输出,否则跳过。
在Apache Spark中,同样存在类似于DistributedCache的功能,称为“广播变量”(Broadcast variable)。其实现原理与DistributedCache非常类似,但提供了更多的数据/文件广播算法,包括高效的P2P算法,该算法在节点数目非常多的场景下,效率远远好于DistributedCache这种基于HDFS共享存储的方式,具体比较可参考“Performance and Scalability of Broadcast in Spark”。使用MapReduce DistributedCache时,用户需要显示地使用File API编写程序从本地读取小表数据,而Spark则不用,它借助Scala语言强大的函数闭包特性,可以隐藏数据/文件广播过程,让用户编写程序更加简单。
假设两个文件,一小一大,且格式类似为:
Key,value,value
Key,value,value
则利用Spark实现map-side的算法如下:
var table1 = sc.textFile(args(1))
var table2 = sc.textFile(args(2))
// table1 is smaller, so broadcast it as a map<String, String>
var pairs = table1.map { x =>
var pos = x.indexOf(',')
(x.substring(0, pos), x.substring(pos + 1))
}.collectAsMap
var broadCastMap = sc.broadcast(pairs) //save table1 as map, and broadcast it
// table2 join table1 in map side
var result = table2.map { x =>
var pos = x.indexOf(',')
(x.substring(0, pos), x.substring(pos + 1))
}.mapPartitions({ iter =>
var m = broadCastMap.value
for{
(key, value) <- iter
if(m.contains(key))
} yield (key, (value, m.get(key).getOrElse("")))
})
result.saveAsTextFile(args(3)) //save result to local file or HDFS
(2)Reduce-side Join
当两个文件/目录中的数据非常大,难以将某一个存放到内存中时,Reduce-side Join是一种解决思路。该算法需要通过Map和Reduce两个阶段完成,在Map阶段,将key相同的记录划分给同一个Reduce Task(需标记每条记录的来源,便于在Reduce阶段合并),在Reduce阶段,对key相同的进行合并。
Spark提供了Join算子,可以直接通过该算子实现reduce-side join,但要求RDD中的记录必须是pair,即RDD[KEY, VALUE],同样前一个例利用Reduce-side join实现如下:
var table1 = sc.textFile(args(1))
var table2 = sc.textFile(args(2))
var pairs = table1.map{x =>
var pos = x.indexOf(',')
(x.substring(0, pos), x.substring(pos + 1))
}
var result = table2.map{x =>
var pos = x.indexOf(',')
(x.substring(0, pos), x.substring(pos + 1))
}.join(pairs)
result.saveAsTextFile(args(3))
(3)总结
本文介绍了Spark中map-side join和reduce-side join的编程思路,希望对大家有借鉴意义。但需要注意的是,在使用这两种算法处理较大规模的数据时,通常需要对多个参数进行调优,否则可能会产生OOM问题。通常需要调优的相关参数包括,map端数据输出buffer大小,reduce端数据分组方法(基于map还是基于sort),等等。
(4)两个问题
问题1:如果在map-side join中,不使用以下语句对文件1进行广播,
var broadCastMap = sc.broadcast(pairs)
也可以在后面程序中直接使用变量pairs存储的数据进行join,这两种方式有什么异同,性能会有何不同?
问题2:将map-side join中的以下语句:
mapPartitions({ iter =>
var m = broadCastMap.value
for{
(key, value) <- iter
if(m.contains(key))
} yield (key, (value, m.get(key).getOrElse("")))
改为:
var m = broadCastMap.value //这一句放在var table2 = sc.textFile(args(2))后面
map {case (key, value) =>
if(m.contains(key)) (key, (value, m.get(key).getOrElse("")))
}
最终结果是有问题的,为什么? 本文两个示例程序可以从百度网盘上下载,地址为Spark-Join-Exmaple。
原创文章,转载请注明: 转载自董的博客 http://dongxicheng.org/framework-on-yarn/apache-spark-join-two-tables/
实现Map-side Join和Reduce-side Join(转)的更多相关文章
- hadoop 多表join:Map side join及Reduce side join范例
最近在准备抽取数据的工作.有一个id集合200多M,要从另一个500GB的数据集合中抽取出所有id集合中包含的数据集.id数据集合中每一个行就是一个id的字符串(Reduce side join要在每 ...
- hadoop的压缩解压缩,reduce端join,map端join
hadoop的压缩解压缩 hadoop对于常见的几种压缩算法对于我们的mapreduce都是内置支持,不需要我们关心.经过map之后,数据会产生输出经过shuffle,这个时候的shuffle过程特别 ...
- Map Reduce Application(Join)
We are going to explain how join works in MR , we will focus on reduce side join and map side join. ...
- Reduce Side Join实现
关于reduce边join,其最重要的是使用MultipleInputs.addInputPath这个api对不同的表使用不同的Map,然后在每个Map里做一下该表的标识,最后到了Reduce端再根据 ...
- MapReduce的Reduce side Join
1. 简单介绍 reduce side join是全部join中用时最长的一种join,可是这样的方法可以适用内连接.left外连接.right外连接.full外连接和反连接等全部的join方式.r ...
- 转载:left join和left semi join的联系和区别
1.联系 他们都是 hive join 方式的一种,join on 属于 common join(shuffle join/reduce join),而 left semi join 则属于 map ...
- 1122MySQL性能优化之 Nested Loop Join和Block Nested-Loop Join(BNL)
转自http://blog.itpub.net/22664653/viewspace-1692317/ 一 介绍 相信许多开发/DBA在使用MySQL的过程中,对于MySQL处理多表关联的方式或者说 ...
- SQL JOIN\SQL INNER JOIN 关键字\SQL LEFT JOIN 关键字\SQL RIGHT JOIN 关键字\SQL FULL JOIN 关键字
SQL join 用于根据两个或多个表中的列之间的关系,从这些表中查询数据. Join 和 Key 有时为了得到完整的结果,我们需要从两个或更多的表中获取结果.我们就需要执行 join. 数据库中的表 ...
- JavaScript 中 map、foreach、reduce 间的区别
一直对map.foreach.reduce这些函数很是生疏,今天看underscorejs时好好研究了一下,一研究我就更懵了,这不是一样嘛,都是遍历,所以我就去知乎找了一下,整理出了比较好的几个说法. ...
- Swift函数编程之Map、Filter、Reduce
在Swift语言中使用Map.Filter.Reduce对Array.Dictionary等集合类型(collection type)进行操作可能对一部分人来说还不是那么的习惯.对于没有接触过函数式编 ...
随机推荐
- JavaScript - BOM
window 对象 window 对象是BOM的核心对象,也是ECMAScript规定的Global对象. 无法跨浏览精确获得窗口左边和上边的精确值,同样也无法确定浏览器窗口本身的大小,但是可以取得页 ...
- gdb optimized out错误解决
转自:http://blog.csdn.net/cws1214/article/details/12023093 when linux gdb debug, print a variable, suc ...
- 为GDI函数增加透明度处理
用户对客户端的UI的要求越来越高,采用alpha通道对前景背景做混合是提高UI质量的重要手段. UI开发离不开GDI,然后要用传统的GDI函数来处理alpha通道通常是一个恶梦:虽然有AlphaBle ...
- android AsyncTask介绍(转)
android AsyncTask介绍 AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接 ...
- POJ 3140 Contestants Division 树形DP
Contestants Division Description In the new ACM-ICPC Regional Contest, a special monitoring and su ...
- HDU 1561 The more, The Better 树形DP
The more, The Better Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M ...
- Linux C编程(1) vim及gcc命令
1. 输入以下命令可以启动vi: (1) vi:不指定文件名,在保存文件时需要指定文件名. (2) vi 文件名:该文件既可以是已存在的,也可以是新建的. (3) vi ...
- LoadRunner11录制APP脚本(2)
通过安卓模拟器实现LoadRunner11录制APP脚本 http://www.51testing.com/html/24/15110424-3686857.html http://www.51tes ...
- POJ 2549 二分+HASH
题目链接:http://poj.org/problem?id=2002 题意:给定一个n个数字组成的序列,然后求出4个数使得a+b+c=d,求d的最大值.其中a,b,c,d要求是给定序列的数,并且不能 ...
- DSP using MATLAB示例 Example3.5
代码: n = [0:10]; x = (0.9*exp(j*pi/3)).^n; % x(n) = k = -200:200; w = (pi/100)*k; % [0,pi] axis divid ...