10

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

更具体地说,这就是我真正需要做的:

我有两组数据:

  1. 点信息存储为 (tile_number, point_id:point_info) ,这是一个 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 对与每个 tile_number 的所有 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)
4

2 回答 2

8

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

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

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

然后,在 reducer 中,您的输入将具有以下结构:

 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
于 2012-08-03T21:42:46.800 回答
1

所以基本上你在这里有两个选择。Reduce side join 或 Map Side Join 。

在这里,您的组键是“平铺”。在单个减速器中,您将获得点对和线对的所有输出。但是您必须在阵列中缓存点对或线对。如果任何一对(点或线)都非常大,无法放入单个组键(每个唯一的瓦片)的临时数组内存中,那么此方法对您不起作用。请记住,您不必在内存中保存单个组密钥(“tile”)的两个密钥对,一个就足够了

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

于 2012-08-03T23:30:01.797 回答