Hadoop:reducer的输入记录数

时间:2012-12-19 23:42:07

标签: hadoop mapreduce

无论如何,每个reducer进程是否可以确定它必须处理的元素或记录的数量?

2 个答案:

答案 0 :(得分:3)

简短的回答 - 提前没有,减速器不知道可迭代支持多少个值。你可以做到这一点的唯一方法就是在迭代时计算,但你不能再重复迭代迭代。

长答案 - 支持iterable实际上是序列化键/值对的排序字节数组。减速器有两个比较器 - 一个用于按键顺序对键/值对进行排序,另一个用于确定键之间的边界(称为关键分组器)。通常,关键分组器与密钥排序比较器相同。

当迭代特定键的值时,底层上下文检查数组中的下一个键,并使用分组比较器与前一个键进行比较。如果比较器确定它们相等,则迭代继续。否则,此特定键的迭代结束。因此,您可以看到,您无法提前确定如何为任何特定密钥传递值。

如果你创建一个复合键,比如一个Text / IntWritable对,你实际上可以看到这个。对于compareTo方法,首先是Text,然后是IntWritable字段。接下来创建一个Comparator,用作组比较器,它只考虑键的Text部分。现在,当您迭代reducer中的值时,您应该能够观察每次迭代时键的IntWritable部分。

我之前用过的一些代码演示了这种情况,可以在pastebin

找到

答案 1 :(得分:1)

您的reducer类必须扩展MapReducer Reduce类:

Reducer<KEYIN,VALUEIN,KEYOUT,VALUEOUT>

然后必须使用扩展Reduce类中指定的KEYIN / VALUEIN参数实现reduce方法

reduce(KEYIN key, Iterable<VALUEIN> values, org.apache.hadoop.mapreduce.Reducer.Context context)

与给定密钥关联的值可以通过

计算
int count = 0;
Iterator<VALUEIN> it = values.iterator();
while(it.hasNext()){
  it.Next();
  count++;
}

虽然我建议在你的另一个处理过程中进行此计数,以便不会通过你的值集两次。

修改

这是一个向量的示例向量,它会在您添加时动态增长(因此您不必静态声明数组,因此不需要设置值的大小)。这对于非常规数据最有效(IE输入csv文件中每行的列数不相同),但开销最大。

Vector table = new Vector();

Iterator<Text> it = values.iterator();
while(it.hasNext()){

  Text t = it.Next();
  String[] cols = t.toString().split(",");   

  int i = 0;
  Vector row = new Vector(); //new vector will be our row
  while(StringUtils.isNotEmpty(cols[i])){
    row.addElement(cols[i++]); //here were adding a new column for every value in the csv row
  }

  table.addElement(row);
}

然后你可以通过

访问第N行的第M列
table.get(N).get(M);

现在,如果您知道将设置#列,您可以修改它以使用可能更快/更节省空间的数组向量。