2

我有一个值列表作为一个数据源和第二个数据集,其中包含与一个值相关的范围。

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 中的字符联系起来。

4

2 回答 2

3

主要问题是 MapReduce 进行连接的方式要求键完全匹配,并且它在分区器中随机存储事物(默认情况下)。使用 Java MapReduce 可能有很多棘手的方法可以做到这一点。在 Pig 中我能想到的最直接的两个如下。不确定哪个会更快……这取决于数据的性质。


使用叉积:

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;

这是您编写一个 udf 调用的地方explode_range_udf,它接受三个值并返回一个包含范围内每个可能元素的元组包。例如:

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

FLATTEN对包中的每件物品进行记录。

于 2013-04-19T01:23:45.997 回答
2

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

ANSWER = FOREACH DATASET1 GENERATE myBinarySearchUdf(number) 
   as myResult:Tuple(originalNumber:int, dataSet2Id:chararray);
于 2013-04-19T16:55:06.493 回答