2013-04-24 66 views
2

我目前正在编写一个mapreduce程序来查找两个hive表之间的区别。 我的配置单元表分区在一列或多列上。所以文件夹名称包含分区列的值。从mapreduce中读取配置单元表

有什么方法可以读取蜂巢分区表。

它可以在映射器中读取吗​​?

+0

您可能想要编辑您的问题,以强化您正在寻找一种方法来读取在映射器中分区的列的值。现在,回答者可能会想知道如何递归地将所有输入文件添加到MapReduce作业(已在StackOverflow中多次处理)。但是,当部分数据在输入文件夹结构中时重新创建表格似乎是您问题的重要元素。 – 2013-04-25 15:44:01

回答

2

因为底层HDFS数据将被默认在分区蜂巢表作为

table/root/folder/x=1/y=1 
table/root/folder/x=1/y=2 
table/root/folder/x=2/y=1 
table/root/folder/x=2/y=2...., 

你可以建立每个输入通道的司机,并通过多次调用将它们添加到FileInputFormat.addInputPath(工作组织,路径)。您建立的每个文件夹路径的呼叫。

粘贴下面的示例代码。注意如何将路径添加到MyMapper.class。在此示例中,我使用MultipleInputs API。表由“部分”和“xdate”进行分区。

public class MyDriver extends Configured implements Tool { 
    public int run(String[] args) throws Exception { 
     Configuration conf = getConf(); 
     conf.set("mapred.compress.map.output", "true"); 
     conf.set("mapred.output.compression.type", "BLOCK"); 

     Job job = new Job(conf); 
     //set up various job parameters 
     job.setJarByClass(MyDriver.class); 
     job.setJobName(conf.get("job.name")); 
     MultipleInputs.addInputPath(job, new Path(conf.get("root.folder")+"/xdate="+conf.get("start.date")), TextInputFormat.class, OneMapper.class); 
     for (Path path : getPathList(job,conf)) { 
      System.out.println("path: "+path.toString()); 
      MultipleInputs.addInputPath(job, path, Class.forName(conf.get("input.format")).asSubclass(FileInputFormat.class).asSubclass(InputFormat.class), MyMapper.class); 
     } 
     ... 
     ... 
     return job.waitForCompletion(true) ? 0 : -2; 

    } 

    private static ArrayList<Path> getPathList(Job job, Configuration conf) { 
     String rootdir = conf.get("input.path.rootfolder"); 
     String partlist = conf.get("part.list"); 
     String startdate_s = conf.get("start.date"); 
     String enxdate_s = conf.get("end.date"); 
     ArrayList<Path> pathlist = new ArrayList<Path>(); 
     String[] partlist_split = partlist.split(","); 
     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 
     Date startdate_d = null; 
     Date enxdate_d = null; 
     Path path = null; 
     try { 
      startdate_d = sdf.parse(startdate_s); 
      enxdate_d = sdf.parse(enxdate_s); 
      GregorianCalendar gcal = new GregorianCalendar(); 
      gcal.setTime(startdate_d); 
      Date d = null; 
      for (String part : partlist_split) { 
       gcal.setTime(startdate_d); 
       do { 
        d = gcal.getTime(); 
        FileSystem fs = FileSystem.get(conf); 
        path = new Path(rootdir + "/part=" + part + "/xdate=" 
          + sdf.format(d)); 
        if (fs.exists(path)) { 
         pathlist.add(path); 
        } 
        gcal.add(Calendar.DAY_OF_YEAR, 1); 
       } while (d.before(enxdate_d)); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return pathlist; 
    } 

    public static void main(String[] args) throws Exception { 
     int res = ToolRunner.run(new Configuration(), new MyDriver(), args); 
     System.exit(res); 
    } 
} 
+0

谢谢。无论如何,我们可以从mapreduce中读取RCFile吗? – kabalas 2013-04-25 12:30:15

+1

在MapReduce作业中,您可以调用'context.getInputSplit()'来获得一个'InputSplit'对象,其中包含有关输入来自哪里的信息。 'FileSplit'实现'InputSplit'并且有一个'getPath()'方法,你可以解析它以获取被分区的列的值。我找不到任何有效的代码示例,因此使用[docs](http://hadoop.apache.org/docs/current/api/org/apache/hadoop/mapred/FileSplit.html)可能是您最好的选择。如果你对[hive源代码](https://github.com/apache/hive)感兴趣,可能会有帮助。 – 2013-04-25 15:38:52