Hadoop 从MapReduce作业向配置单元添加分区
我是Hive和MapReduce的新手,非常感谢您的回答并提供正确的方法 我在hive中定义了一个外部表Hadoop 从MapReduce作业向配置单元添加分区,hadoop,mapreduce,hive,partitioning,Hadoop,Mapreduce,Hive,Partitioning,我是Hive和MapReduce的新手,非常感谢您的回答并提供正确的方法 我在hive中定义了一个外部表logs,该表在date and origin server上分区,外部位置在hdfs上/data/logs/。我有一个MapReduce作业,它获取这些日志文件并将它们拆分,然后存储在上面提到的文件夹下。像 "/data/logs/dt=2012-10-01/server01/" "/data/logs/dt=2012-10-01/server02/" ... ... 从MapReduce
logs
,该表在date and origin server上分区,外部位置在hdfs上/data/logs/
。我有一个MapReduce作业,它获取这些日志文件并将它们拆分,然后存储在上面提到的文件夹下。像
"/data/logs/dt=2012-10-01/server01/"
"/data/logs/dt=2012-10-01/server02/"
...
...
从MapReduce作业中,我想向配置单元中的表日志添加分区。我知道这两种方法
对于方法二,我只看到了
INSERT OVERWRITE
的示例,这不是我的选项。有没有办法在作业结束后将这些新分区添加到表中?要从Map/Reduce作业中执行此操作,我建议使用ApacheHCatalog,这是一个在Hadoop下标记的新项目
HCatalog实际上是HDFS之上的一个抽象层,因此您可以以标准化的方式编写输出,无论是从Hive、Pig还是M/R。您可以使用输出格式HCatOutputFormat
直接从Map/Reduce作业将数据加载到Hive中。下面是一个例子
当前用于为(A=1,b=1)写出特定分区的代码示例如下所示:
Map<String, String> partitionValues = new HashMap<String, String>();
partitionValues.put("a", "1");
partitionValues.put("b", "1");
HCatTableInfo info = HCatTableInfo.getOutputTableInfo(dbName, tblName, partitionValues);
HCatOutputFormat.setOutput(job, info);
Map partitionValues=newhashmap();
分区价值。将(“a”、“1”);
分区价值。投入(“b”、“1”);
HCatTableInfo=HCatTableInfo.getOutputTableInfo(数据库名、tblName、分区值);
设置输出(作业、信息);
要写入多个分区,必须使用上述每个分区启动单独的作业
您还可以将动态分区与HCatalog一起使用,在这种情况下,您可以在同一个作业中加载任意多个分区
我建议您在上面提供的网站上进一步阅读HCatalog,如果需要的话,它会给您提供更多的细节。事实上,事情比这要复杂一点,这是不幸的,因为它在官方来源中没有记录(截至目前为止),需要几天的时间才能弄清楚 我发现,我需要执行以下操作,以使HCatalog Mapreduce作业能够写入动态分区: 在工作的记录编写阶段(通常是reducer),我必须手动将动态分区(HCatFieldSchema)添加到HCatSchema对象中 问题在于HCatOutputFormat.getTableSchema(配置)实际上并没有返回分区字段。它们需要手动添加
HCatFieldSchema hfs1 = new HCatFieldSchema("date", Type.STRING, null);
HCatFieldSchema hfs2 = new HCatFieldSchema("some_partition", Type.STRING, null);
schema.append(hfs1);
schema.append(hfs2);
下面是使用HCatalog在一个作业中使用动态分区写入多个表的代码,该代码已在Hadoop 2.5.0、Hive 0.13.1上进行了测试:
/。。。作业设置、InputFormatClass等。。。
字符串dbName=null;
String[]tables={“table0”,“table1”};
setOutputFormatClass(MultiOutputFormat.class);
MultiOutputFormat.JobConfigurer configurer=MultiOutputFormat.createConfigurer(作业);
List partitions=new ArrayList();
添加(0,“分区0”);
分区。添加(1,“分区1”);
HCatFieldSchema partition0=新的HCatFieldSchema(“partition0”,TypeInfoFactory.stringTypeInfo,null);
HCatFieldSchema partition1=新的HCatFieldSchema(“partition1”,TypeInfoFactory.stringTypeInfo,null);
for(字符串表:表){
configurer.addOutputFormat(表,HCatOutputFormat.class,BytesWritable.class,CatRecord.class);
OutputJobInfo OutputJobInfo=OutputJobInfo.create(dbName,table,null);
outputJobInfo.SetDynamicPartitioningKey(分区);
HCatOutputFormat.setOutput(
configurer.getJob(表),outputJobInfo
);
HCatSchema schema=HCatOutputFormat.getTableSchema(configurer.getJob(table.getConfiguration());
schema.append(partition0);
schema.append(partition1);
HCatOutputFormat.setSchema(
配置器.getJob(表),
模式
);
}
configurer.configure();
返回作业。等待完成(true)?0 : 1;
制图员:
公共静态类MyMapper扩展了Mapper{
@凌驾
受保护的void映射(LongWritable键、文本值、上下文)引发IOException、InterruptedException{
HCatRecord=newdefaulthcatRecord(3);//包括分区
set(0,value.toString());
//必须在非分区字段之后设置分区
record.set(1,“0”);//分区0=0
record.set(2,“1”);//partition1=1
MultiOutputFormat.write(“table0”,null,记录,上下文);
MultiOutputFormat.write(“表1”,null,记录,上下文);
}
}
我使用的是cloudera发行版,它没有附带HCatalog。Oozie能成为一种选择吗?如果是这样的话,关于如何实现它有什么想法吗?如果您不想修改table语句,不想执行insert覆盖,也不能使用HCatalog,我认为这将是一件复杂的事情。Oozie只是一个工作流调度器,您仍然需要在某个地方定义作业。