【问题标题】:MapReduce: Why Can't I do a Secondary Sort like this (Hadoop)?MapReduce:为什么我不能像这样(Hadoop)进行二次排序?
【发布时间】:2014-01-24 20:41:53
【问题描述】:

我使用正确的方法实现了二级排序:复合键、复合键比较器类、自然键分组比较器类和自然键分区器类。

但是,在我知道这是必要的之前,我做了以下事情:

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      }

我假设如果我把它放进去,它仍然不起作用(鉴于每个人都建议使用上面列出的方法进行二级排序)。为什么不呢?

【问题讨论】:

    标签: hadoop mapreduce


    【解决方案1】:

    当您希望您的值按辅助键排序并按主键分组时,通常会使用辅助排序。仅使用复合键仅允许您按主键和辅助键进行分组;一旦到达相应的减速器,它就无法以任何排序顺序获取您的值。

    具体来说:“姓名”为主键,“时间”为辅键,

    使用二次排序:每个reducer获取一个“Name”对应的所有值,并按排序顺序获取“Time”的每个数据点,例如,Name:Bob, Time:1,2,3,...

    仅使用复合键:每个 reducer 获取与每个 "Name","Time" 对对应的所有值。无法保证同一个 reducer 将所有名称、时间对对应于相同名称,因此无法保证 Bob 的值按时间顺序处理。

    【讨论】:

    • 我不明白的是,鉴于我已经写了equals,为什么每个reducer 会获取与每个“名称”、“时间”对相对应的所有值,而不是每个“名称”, comparecompareto 方法?如果 Sort/Reduce 阶段不使用这些方法中的任何一种来决定“Name”、“Time”,它通过哪种机制决定使用“Name”、“Time”?
    • 这将是映射器输出键/减速器输入键。它在 JobConf 中定义,例如,hadoop.apache.org/docs/stable/api/org/apache/hadoop/mapred/…
    【解决方案2】:

    您可以尝试将name 的类型更改为hadoop 的Text。这对我有帮助。

    【讨论】:

      猜你喜欢
      • 2014-08-13
      • 1970-01-01
      • 2016-01-04
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多