2012-08-03 44 views
9

有谁知道如何在Hadoop中的两个数据集之间实现Natural-Join操作?在Mapreduce/Hadoop中加入两个数据集

更具体地讲,这里就是我究竟需要做的:

我有两组数据:被存储为(tile_number,point_id:point_info)

  1. 点的信息,这是1:n键值对。这意味着对于每个tile_number,可能有几个point_id:point_info

  2. 行信息存储为(tile_number,line_id:line_info),这又是1:m键值对,并且对于每个tile_number,可能有不止一个line_id:line_info

正如你所看到的,tile_numbers在两个数据集之间是相同的。现在我真正需要的是基于每个tile_number来加入这两个数据集。换句话说,对于每个tile_number,我们有n个point_id:point_info和m个line_id:line_info。我想要做的是加入point_id的所有对:point_info所有对line_id的:line_info为每tile_number


为了澄清,这里有一个例子:

对于点对:

(tile0, point0) 
(tile0, point1) 
(tile1, point1) 
(tile1, point2) 

对线对:

(tile0, line0) 
(tile0, line1) 
(tile1, line2) 
(tile1, line3) 

我要的是如下:

瓦片0:

(tile0, point0:line0) 
(tile0, point0:line1) 
(tile0, point1:line0) 
(tile0, point1:line1) 

瓦片1:

(tile1, point1:line2) 
(tile1, point1:line3) 
(tile1, point2:line2) 
(tile1, point2:line3) 

回答

7
使用

输出的标题密钥和点/线为值的映射器。您必须区分点输出值和线输出值。例如,你可以使用特殊字符(即使二进制方法会好得多)。

所以地图的输出将是这样的:

tile0, _point0 
tile1, _point0 
tile2, _point1 
... 
tileX, *lineL 
tileY, *lineK 
... 

然后,在减速,您输入都会有这样的结构:

tileX, [*lineK, ... , _pointP, ...., *lineM, ..., _pointR] 

,你将不得不采取的价值观分开点和线,做一个交叉产品并输出每一对交叉产品,如下:

tileX (lineK, pointP) 
tileX (lineK, pointR) 
... 

如果您已经可以轻松区分点值和线值(取决于您的应用规范),则不需要特殊字符(*,_)

关于您必须在减速机: 你先在整个值列表循环,他们分成2列表:

List<String> points; 
List<String> lines; 

然后做使用2嵌套for循环的跨产品。 然后通过结果列表,并为每个元素的输出迭代:

tile(current key), element_of_the_resulting_cross_product_list 
+0

很大。但我应该如何在减少部分进行交叉产品? – reza 2012-08-03 21:55:42

+0

我编辑了我的答案! – Razvan 2012-08-03 22:01:48

+4

太棒了,但这只适用于如果您可以将所有点/线条放入内存以便将它们存储在两个提及的列表中。我恐怕在我的大型数据集中并不是这样的情况:( – reza 2012-08-03 22:10:04

1

所以基本上你有两种选择here.Reduce侧加入或地图边加入。

这里你的组密钥是“瓦”。在单个reducer中,您将获得来自点对和线对的所有输出。但是你必须缓存数组中的点对或线对。如果其中任何一对(点或线)非常大,都不能放入临时阵列内存中的单组键(每个独立的磁贴),那么这种方法不适用于您。记住你不必为内存中的单个组密钥(“tile”)保存两个密钥对,一个将足够

如果单个组密钥的两个密钥对都很大,那么你将不得不尝试map-side join。但它有一些特殊的要求。但是,通过对两个数据运行相同数量的缩减器的某些映射/减少作业,可以通过对数据进行预处理来满足这些要求。