Hadoop 从MapReduce作业向配置单元添加分区

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

我是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作业中,我想向配置单元中的表日志添加分区。我知道这两种方法

  • alter table命令--alter table命令太多
  • 添加动态分区

  • 对于方法二,我只看到了
    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只是一个工作流调度器,您仍然需要在某个地方定义作业。