正在为辅助排序创建复合关键字类



我正在尝试为Secondary Sort创建一个String uniqueCarrierint month的复合键类。有人能告诉我吗,相同的步骤是什么吗。

由于您在compareTo方法中没有使用uniqueCarrier,因此看起来您遇到了相等问题。您需要在compareTo和equals方法中使用uniqueCarrier(也定义equals方法)。来自java语言参考

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

您还可以实现RawComparator,这样您就可以在不进行反序列化的情况下对它们进行比较,从而获得更快的性能。

然而,我建议(像往常一样)不要自己写像"二次排序"这样的东西。这些已经在Pig和Hive等项目中实现(以及数十个其他优化)。例如,如果你使用Hive,你只需要写:

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

上面的内容比试图弄清楚如何编写Secondary Sorts要简单得多(最终,当你需要再次使用它时,如何以通用的方式进行)。MapReduce应该被视为一种低级别的编程范式,并且只有当您需要从Pig或Hive等更高级别项目中无法获得的高性能优化时才应该使用(IMHO)。

编辑:忘记提及分组比较器,请参阅Matt的回答

您的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 partitionner调用,以在减速器之间分配工作。

我还将编写自定义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关于实现RawComparator的建议,以防止每次都必须对对象进行解组。

最新更新