我有多个输入源,我使用Sqoop的codegen工具为每个输入源生成自定义类
public class SQOOP_REC1 extends SqoopRecord implements DBWritable, Writable
public class SQOOP_REC2 extends SqoopRecord implements DBWritable, Writable
在Map侧,基于输入源,我相应地创建了上述2个类的对象。
我将密钥作为“Text”类型,因为我有2种不同类型的值,所以我将值输出类型保持为“可写”。
在reduce方面,我接受值类型为Writable。
public class SkeletonReduce extends Reducer<Text,Writable, Text, Text> {
public void reduce(Text key, Iterable<Writable> values, Context context) throws IOException,InterruptedException {
}
}
我也设置了
job.setMapOutputValueClass(Writable.class);
在执行期间,它根本不会进入reduce函数。
有人可以告诉我是否可以这样做?如果是这样,我做错了什么?
答案 0 :(得分:0)
您不能指定Writable
作为输出类型;它必须是具体的类型。所有记录都需要在Mapper
和Reducer
中具有相同(具体)的键和值类型。如果您需要不同的类型,您可以创建某种混合Writable
,其中包含“A”或“B”。它有点难看,但有效,并且在Mahout中做了很多。例如。
但我不知道为什么这会导致减速器无法运行;根据这些信息,这可能是相当独立的,并且无法回答。
答案 1 :(得分:0)
考虑为您的值类型扩展GenericWritable。您需要定义允许的类集(在您的情况下为SQOOP_REC1和SQOOP_REC2),并且它不那么有效,因为它在readFields方法中创建了新的对象实例(但如果您有一小组类,则可以覆盖它,只有两种类型的实例变量,以及一个表示哪一个有效的标志)
答案 2 :(得分:0)
好的,我想我想出了如何做到这一点。根据Doug Cutting自己提出的建议
http://grokbase.com/t/hadoop/common-user/083gzhd6zd/multiple-output-value-classes
我使用ObjectWritable
包装了这个类ObjectWritable obj = new ObjectWritable(SQOOP_REC2.class,sqoop_rec2);
然后在Reduce方面,我可以获取包装类的名称并将其转换回原始类。
if(val.getDeclaredClass().getName().equals("SQOOP_REC2")){
SQOOP_REC2temp = (SQOOP_REC2) val.get();
别忘了
job.setMapOutputValueClass(ObjectWritable.class);