0

我有多个输入源,我使用 Sqoop 的 codegen 工具为每个输入源生成自定义类

public class SQOOP_REC1 extends SqoopRecord  implements DBWritable, Writable

public class SQOOP_REC2 extends SqoopRecord  implements DBWritable, Writable

在 Map 方面,根据输入源,我相应地创建了上述 2 个类的对象。

我将键作为“文本”类型,并且由于我有 2 种不同类型的值,因此我将值输出类型保持为“可写”。

在减少方面,我接受值类型为可写。

   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函数。

有人可以告诉我是否可以这样做?如果是这样,我做错了什么?

4

3 回答 3

0

考虑为您的值类型扩展 GenericWritable。您需要定义允许的类集(在您的情况下为 SQOOP_REC1 和 SQOOP_REC2),并且效率不高,因为它在 readFields 方法中创建了新的对象实例(但如果您有一小部分类,则可以覆盖它,只具有两种类型的实例变量,以及一个指示哪个是有效的标志)

于 2012-04-24T13:01:24.143 回答
0

您不能指定Writable为您的输出类型;它必须是一个具体的类型。所有记录都需要在Mappers 和Reducers 中具有相同的(具体)键和值类型。如果您需要不同的类型,您可以创建某种Writable内部包含“A”或“B”的混合。它有点难看,但很有效,例如在 Mahout 中做了很多工作。

但我不知道为什么这会使减速器无法运行;根据此信息,这可能是完全不同的事情并且无法回答。

于 2012-04-24T12:38:35.373 回答
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);
于 2012-04-25T05:21:37.107 回答