1

基于这里的这个例子,这是可行的。在我的数据集上尝试过同样的方法。

样本数据集:

OBSERVATION;2474472;137176;
OBSERVATION;2474473;137176;
OBSERVATION;2474474;137176;
OBSERVATION;2474475;137177;

将每一行视为字符串,我的 Mapper 输出为:

键-> 字符串[2],值-> 字符串。

我的分区代码:

@Override
public int getPartition(Text key, Text value, int reducersDefined) {

    String keyStr = key.toString();
    if(keyStr == "137176") {
        return 0;
    } else {
        return 1 % reducersDefined;
    }
}

在我的数据集中,大多数 id 是 137176。Reducer 声明为 -2。我希望有两个输出文件,一个用于 137176,第二个用于剩余的 ID。我得到两个输出文件,但是 Id 均匀分布在两个输出文件上。我的程序出了什么问题?

4

1 回答 1

0
  1. 在 Driver 方法中明确设置要使用自定义分区器,方法是使用:job.setPartitionerClass(YourPartitioner.class);。如果您不这样做,则使用默认的 HashPartitioner。

  2. 将字符串比较方法从 更改==.equals()。即,更改if(keyStr == "137176") {if(keyStr.equals("137176")) {.
    为了节省一些时间,也许在分区器的开头声明一个新的 Text 变量会更快,如下所示:Text KEY = new Text("137176");然后,无需每次都将输入键转换为 String,只需将其与KEY变量进行比较(再次使用equals()方法)。但也许这些是等价的。所以,我的建议是:

    文本键 = 新文本(“137176”);
    
    @覆盖
    public int getPartition(Text key, Text value, int reducersDefined) {
        返回 key.equals(KEY) ?0 : 1 % 减速器定义;    
    }
    

另一个建议,如果网络负载很重,将映射输出键解析为 VIntWritable 并相应地更改分区器。

于 2015-07-20T14:05:47.687 回答