有人知道如何在Hadoop中实现两个数据集之间的自然联接操作吗?
更具体地说,我需要做的是:
我有两组数据:
-
存储为(tile_number,point_id:point_info)的点信息,这是一个1:n键值对。这意味着对于每个tile_number,可能有几个point_id:point_info
-
存储为(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。我想做的是将每个tile_number 的所有point_id:point_info对与line_id:line_info对连接起来
为了澄清,这里有一个例子:
对于点对:
(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)
使用一个映射器,将标题输出为键,将点/线输出为值。您必须区分点输出值和线输出值。例如,您可以使用一个特殊字符(即使二进制方法会更好)。
因此,地图输出将类似于:
tile0, _point0
tile1, _point0
tile2, _point1
...
tileX, *lineL
tileY, *lineK
...
然后,在减速器上,您的输入将具有以下结构:
tileX, [*lineK, ... , _pointP, ...., *lineM, ..., _pointR]
你必须把点和线分开,做一个叉积,然后输出每对叉积,就像这样:
tileX (lineK, pointP)
tileX (lineK, pointR)
...
如果您已经可以很容易地区分点值和线值(取决于您的应用程序规范),则不需要特殊字符(*,_)
关于您必须在减速器中进行的叉积:您首先遍历整个值List,将它们分成2个列表:
List<String> points;
List<String> lines;
然后使用2个嵌套for循环进行叉积。然后对结果列表进行迭代,并为每个元素输出:
tile(current key), element_of_the_resulting_cross_product_list
所以这里基本上有两个选项。减少边连接或映射边连接。
这里你的组密钥是"tile"。在一个归约器中,你将得到点对和线对的所有输出。但是您必须在数组中缓存点对或线对。如果其中一对(点或线)非常大,都无法放入单个组键(每个唯一瓦片)的临时数组内存,则此方法将不适用。记住对于内存中的单个组密钥("tile"),您不必同时持有两个密钥对,一个就足够了。
如果单个组密钥的两个密钥对都很大,那么您将不得不尝试映射侧连接。但它有一些特殊的要求。然而,您可以通过一些映射/减少作业对数据进行预处理来满足这些要求,这些作业为两个数据运行相同数量的减少器。