Hadoop 清管器映射减少作业,以将值放置在适当范围内

Hadoop 清管器映射减少作业,以将值放置在适当范围内,hadoop,mapreduce,apache-pig,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 我想创建某种类型的“联接”,将数据集1中的值与数据集2中的字符绑定。主要问题是MapReduce进行联接的方式要求键精确匹配,并且它在分区器中随机存储内容(默认情况下)。使用J

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

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

我想创建某种类型的“联接”,将数据集1中的值与数据集2中的字符绑定。

主要问题是MapReduce进行联接的方式要求键精确匹配,并且它在分区器中随机存储内容(默认情况下)。使用JavaMapReduce可能有很多棘手的方法。下面是我能想到的关于猪的两个最简单的例子。不确定哪一个会更快。。。这取决于数据的性质


使用叉积:

C = CROSS A, B;
D = FILTER C BY $1 >= $2 AND $1 <= $3;
在这里,您可以编写一个名为
explode\u range\u udf
的udf,它接受这三个值并返回一组元组,其中包含范围中的每个可能元素。例如:

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

展平
为包中的每一项创建记录。

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

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

多大(大约)每个数据集都可能是吗?不确定,我的猜测是数据集1可能更大。第二个数据集可能是较少的200k-500k行条目。如果假设一个数据集比另一个数据集大有好处,我会好奇地看到这两个实现。酷。我不知道你可以在Pig中这样做(但我并不感到惊讶)。在代码中的什么地方可以将数据集加载到内存中,这样它就不会在每次UDF调用时都重新加载数据集?没有在后端调用的初始化函数,因此在O'Reilly关于pig的书中,他们说唯一好的方法是使用if(dataSet==null)之类的函数将数据集延迟加载到exec函数的内存中{dataSet=initializeDataSet()}。这样,它只能在第一次调用时加载。
ANSWER = FOREACH DATASET1 GENERATE myBinarySearchUdf(number) 
   as myResult:Tuple(originalNumber:int, dataSet2Id:chararray);