我使用正确的方法实现了Secondary Sort:复合键,复合键比较器类,自然键分组比较器类和自然键分区器类。
然而,在我得知这是必要的之前,我做了以下几点:
class CompositeKey extends WritableComparable<CompositeKey> {
String name; // Natural Key
Date time; // Secondary Sort on this value
// Constructor
public void readFields(DataInput in) { ... }
public void readFields(DataInput out) { ... }
public int compareTo(CompositeKey compositeKey) {
int result = getName().compareTo(compositeKey.getName());
if (result == 0) {
result = getTime().compareTo(compositeKey.getTime());
}
return result
}
public boolean equals(Object compositeKey) {
// Similar code to compareTo()
}
}
我认为Mapper会发出由CompositeKey组合在一起的值,其相等性将由compareTo或equals方法确定。
为什么这种方法不起作用?
鉴于大多数情况下Mapper发出的Key类是.. hadoop.io.Text类,MapReduce如何计算成员变量bytes
是需要比较的为了分组价值?为什么不能像上面的班级那样使用更高级的逻辑进行二次排序?
编辑我刚才注意到了..hadoop.io.Text:
的源代码350 /** A WritableComparator optimized for Text keys. */
351 public static class Comparator extends WritableComparator {
352 public Comparator() {
353 super(Text.class);
354 }
355
356 @Override
357 public int compare(byte[] b1, int s1, int l1,
358 byte[] b2, int s2, int l2) {
359 int n1 = WritableUtils.decodeVIntSize(b1[s1]);
360 int n2 = WritableUtils.decodeVIntSize(b2[s2]);
361 return compareBytes(b1, s1+n1, l1-n1, b2, s2+n2, l2-n2);
362 }
363 }
364
365 static {
366 // register this comparator
367 WritableComparator.define(Text.class, new Comparator());
368 }
我假设如果我把它放入,它仍然不起作用(鉴于每个人都建议做上面列出的方法进行二次排序)。为什么不呢?
答案 0 :(得分:0)
如果希望按主键对值进行排序并按主键分组,则通常会使用辅助排序。只使用复合键只允许您按主键和辅助键分组;一旦到达相应的Reducer,它就无法以任何排序顺序获取值。
具体来说:“Name”是主键,“Time”是辅助键,
使用二级排序:每个reducer获取与一个“Name”对应的所有值,并按排序顺序获取“Time”的每个数据点,例如Name:Bob,Time:1,2,3,...
仅使用复合键:每个reducer获取与每个“Name”,“Time”对相对应的所有值。无法保证相同的reducer将所有名称,时间对对应于同一名称,因此无法保证Bob的值按时间顺序处理。
答案 1 :(得分:0)
您可以尝试将name
的类型更改为hadoop Text
。这帮助了我。