Hadoop中的自定义分区程序

时间:2013-07-09 17:31:36

标签: hadoop apache-pig hadoop-partitioning

我有一些数据是由0到200万的范围内的ID键入的,我需要将其分成0-5mil,5mil - 10mil等范围内的数据。

我试图在Hadoop上使用自定义分区程序来完成最后一部分,以便我的代码的最后一部分看起来像这样:

Conns = FOREACH ConnsGrouped GENERATE group as memberId, $1.companyId as companyIds;
ConnsPartitioned = DISTINCT Conns PARTITION BY com.mypackage.SearchNodePartitioner PARALLEL 50;

rmf $connections_file

Store ConnsPartitioned INTO 'test' using AvroStorage(...);

我的分区看起来像这样:

public class SearchNodePartitioner<Long, V> implements Partitioner<Long, V>
{
    @Override
    public void configure(JobConf conf) 
    {
        // Nothing
    }

    @Override
    public int getPartition(Long key, V value, int numPartitions) 
    {
       return new Double(Math.floor(key / (5.0 * Math.pow(10, 6)))).intValue() % numPartitions;
    }

}

但它似乎根本没有被召唤。即使我用return 1;替换返回行,跨文件的数据似乎也使用默认行为进行散列分发。

2 个答案:

答案 0 :(得分:1)

DISTINCT +自定义分区程序的答案是:你不能再这样做了(正如我刚刚发现的那样)。 DISTINCT现在使用优化的特殊分区器。

请参阅:

http://mail-archives.apache.org/mod_mbox/pig-user/201307.mbox/%3C14FE3AC3-DBA5-4898-AF94-0C34819A0D8B%40hortonworks.com%3E

https://issues.apache.org/jira/browse/PIG-3385

解决方法:

A = //一些元组......;

B = GROUP A BY字段PARTITION BY custom;

存储进入'foo'使用....;

随后:

B = LOAD'foo'使用......;

A = FOREACH B GENERATE FLATTEN($ 1);

答案 1 :(得分:0)

您可以这样做的一种方法是:

A = LOAD ............
SPLIT A INTO B IF <your range condition> , C IF < your range condition>
STORE B ...
STORE C ...

否则你可以试试这个:

 B = FILTER A BY $1 >= <lower_Range> AND $1 <= <upper_Range>;

此外,由于您已经编写了自定义分区程序,因此使用MapReduce可以轻松实现此功能。

您的Map类只会发射对,而您的自定义分区程序会将适当的值范围发送到给定的reducer。但是,一旦您对输入数据进行分区,我不确定您想要做什么,因此我无法评论减速器必须执行的操作。

您可以在Main方法中将自定义分区程序类设置为:

Job.setPartitionerClass(<your custom partitioner class>);