2013-04-24 36 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