我有一个值列表作为一个数据源和第二个数据集,其中包含与一个值相关的范围。
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 中的字符联系起来。
我有一个值列表作为一个数据源和第二个数据集,其中包含与一个值相关的范围。
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 中的字符联系起来。
主要问题是 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
对包中的每件物品进行记录。
如果 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);