为Secondary Sort创建复合键类

时间:2015-03-17 23:41:06

标签: hadoop amazon-web-services mapreduce secondary-sort

我正在尝试为辅助排序创建String uniqueCarrierint month的复合键类。谁能告诉我,同样的步骤是什么。

2 个答案:

答案 0 :(得分:0)

由于您没有在compareTo方法中使用uniqueCarrier,因此看起来您遇到了相同的问题。您需要在compareTo和equals方法中使用uniqueCarrier(也定义一个equals方法)。来自java lang reference

  

当且仅当e1.compareTo(e2)== 0与c1的每个e1和e2的e1.equals(e2)具有相同的布尔值时,C类的自然排序被认为与equals一致。请注意,null不是任何类的实例,并且e.compareTo(null)应该抛出NullPointerException,即使e.equals(null)返回false。

您还可以实现RawComparator,以便您可以比较它们而无需反序列化以获得更快的性能。

但是,我建议(我一直这样做)不要自己写二级排序。这些已经在Pig和Hive等项目中实现(以及其他几十种优化)。例如。如果你使用Hive,你需要写的只有:

SELECT ...
FROM my_table
ORDER BY month, carrier;

上面写的比编写二级排序(并最终需要再次使用它,如何以通用方式完成)更简单。 MapReduce应该被认为是一种低级编程范例,只有在需要高性能优化时才应该使用(恕我直言),而这些优化并不是来自Pig或Hive等高级项目。

编辑:忘了提及分组比较器,请参阅Matt's answer

答案 1 :(得分:0)

您的compareTo()实施不正确。您需要先在uniqueCarrier上排序,然后在month上排序以打破平等:

@Override
public int compareTo(CompositeKey other) {
    if (this.getUniqueCarrier().equals(other.getUniqueCarrier())) {
        return this.getMonth().compareTo(other.getMonth());
    } else {
        return this.getUniqueCarrier().compareTo(other.getUniqueCarrier());
    }
}

但有一个建议:我通常会选择直接将我的属性实现为可写类型(例如,IntWriteable monthText uniqueCarrier)。这样我就可以直接在其上调用writereadFields,也可以使用他们的compareTo。写的代码总是很少......

说到更少的代码,您不必为复合键调用父构造函数。

现在剩下要做的事了:

我的猜测是你仍然缺少hashCode()方法,该方法应该只返回要分组的属性的哈希值,在本例中为uniqueCarrier。默认的Hadoop分区程序调用此方法以在reducers之间分配工作。

我还会编写自定义GroupingComparator和SortingComparator,以确保仅在uniqueCarrier上进行分组,并且排序的行为符合CompositeKey compareTo()

public class CompositeGroupingComparator extends WritableComparator {
    public CompositeGroupingComparator() {
        super(CompositeKey.class, true);
    }

    @Override
    public int compare(WritableComparable a, WritableComparable b) {
        CompositeKey first = (CompositeKey) a;
        CompositeKey second = (CompositeKey) b;

        return first.getUniqueCarrier().compareTo(second.getUniqueCarrier());
    }
}


public class CompositeSortingComparator extends WritableComparator {
    public CompositeSortingComparator()
    {
        super (CompositeKey.class, true);
    }

    @Override
    public int compare (WritableComparable a, WritableComparable b){
        CompositeKey first = (CompositeKey) a;
        CompositeKey second = (CompositeKey) b;

        return first.compareTo(second);
    }
}

然后,告诉你的司机使用这两个:

job.setSortComparatorClass(CompositeSortingComparator.class);
job.setGroupingComparatorClass(CompositeGroupingComparator.class);

修改:另请参阅Pradeep's有关实施RawComparator的建议,以防止每次都要解组到对象,如果您想进一步优化。