猪地图减少工作以将值放在适当的范围内

时间:2013-04-18 16:52:08

标签: hadoop mapreduce apache-pig

我有一个值列表作为一个数据源,第二个数据集包含与值绑定的范围。

Dataset 1:
3
4
6
20
25
38

Dataset 2:
1|3|A
4|10|B
11|20|C
21|30|D
31|31|E
32|38|F
39|40|G

Result:
3,A
4,B
6,B
20,C
25,D
38,F

我想创建某种类型的“JOIN”,将数据集1中的值与数据集2中的字符联系起来。

2 个答案:

答案 0 :(得分:3)

主要问题是MapReduce连接的方式要求密钥完全匹配,并且它在paritioner中随机存储(默认情况下)。使用Java MapReduce可能有很多棘手的方法。我能想到的最简单的两个是下面的。不确定哪个更快......这取决于数据的性质。


使用交叉产品:

C = CROSS A, B;
D = FILTER C BY $1 >= $2 AND $1 <= $3;

这可能很慢!但它完成了工作!


炸掉范围,然后进行连接

B2 = FOREACH B GENERATE FLATTEN(explode_range_udf($1, $2, $3));
C = JOIN A by $1, B2 by $1;

这是你编写一个名为explode_range_udf的udf的地方,它接受三个值并返回一包元组,其中包含范围中的每个可能元素。例如:

explode_range_udf(1,3,A)   ->   {(1,A),(2,A),(3,A)}

FLATTEN根据包中的每个项目创建记录。

答案 1 :(得分:2)

如果Donald Miner的任何一个建议对你来说足够快,我就会这样做,但为了加快速度,如果DataSet 2只有250K-500K条目,那么你应该能够把整个东西放到内存中。因此,您可以:编写一个将DataSet 2存储到内存中的udf(有关如何将hdfs文件存储到DistributedCache中,请参阅getCacheFiles。然后编写一个EvalFunc,其中包含一个DataSet A项,二进制搜索它在DataSet 2中的位置,并返回您想要的答案。

ANSWER = FOREACH DATASET1 GENERATE myBinarySearchUdf(number) 
   as myResult:Tuple(originalNumber:int, dataSet2Id:chararray);