在Spark中读取两个不同的ORC模式文件

时间:2017-08-23 06:41:10

标签: java apache-spark hive orc

我们正在以ORC格式将处理输出保存到HDFC。现在我们有多个模式的文件,我想读取所有文件并创建数据集。

一个选项是我会写一些工作并将所有这些文件转换为单一模式我想避免bcz数据太大而且如果在某一天后模式将再次更改它是一次解决方案我必须重新生成所有数据

我的问题是,是否有任何机制,以便我可以阅读这些文件 假设我在阅读时会提供更高的模式,如果任何一个orc文件中没有某个字段,读者将自动分配空值。

2 个答案:

答案 0 :(得分:1)

我有similar problem。 ORC架构合并是一个开放的feature request,我们也在评论中像其他用户一样切换到镶木地板。

仍然可以(不推荐,因为它非常慢)按文件加载文件并将其保存到.parquet,然后使用自动模式合并加载所有.parquet文件并将大内存保存到。兽人

答案 1 :(得分:0)

AIBOTNET -

使用此命令将不同模式的ORC文件合并为单个ORC文件。我的架构是:

  1. 文件1:第一个:int,第二个:int
  2. file 2:first:int,fourth:string
  3. file 3:first:int,third:map
  4. 如果您需要,我也可以发布文件生成器。

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.FileSystem;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
    import org.apache.orc.OrcFile;
    import org.apache.orc.Reader;
    import org.apache.orc.RecordReader;
    import org.apache.orc.TypeDescription;
    import org.apache.orc.Writer;
    
    import com.google.common.collect.ImmutableList;
    
    public class ReaderSample {
    
      public static void main(String[] args) throws IOException {
    
        Path testFilePath1 = new Path("file1.orc");
        Path testFilePath2 = new Path("file2.orc");
        Path testFilePath3 = new Path("file3.orc");
        Path mergePath = new Path("merge.orc");
        Configuration conf = new Configuration();
    
        FileSystem fileSystem = mergePath.getFileSystem(conf);
        fileSystem.delete(mergePath, false);
    
        List<Path> fileList = ImmutableList.of(testFilePath1, testFilePath2, testFilePath3);
    
        TypeDescription schema = mergeSchema(conf, fileList);
        System.out.println(schema);
        try (Writer writer = OrcFile.createWriter(mergePath, OrcFile.writerOptions(conf)
                                                                    .setSchema(schema))) {
          VectorizedRowBatch writerBatch = schema.createRowBatch();
          for (Path file : fileList) {
            merge(file, conf, writer, writerBatch, schema);
          }
        }
      }
    
      private static TypeDescription mergeSchema(Configuration conf, List<Path> fileList) throws IOException {
        List<TypeDescription> schemaList = new ArrayList<>();
        for (Path path : fileList) {
          Reader reader = OrcFile.createReader(path, OrcFile.readerOptions(conf));
          schemaList.add(reader.getSchema());
        }
    
        TypeDescription masterSchema = new TypeDescription(TypeDescription.Category.STRUCT);
        for (TypeDescription td : schemaList) {
          List<String> fieldNames = td.getFieldNames();
          for (int f = 0; f < fieldNames.size(); f++) {
            String field = fieldNames.get(f);
            List<String> mergeFields = masterSchema.getFieldNames();
            int indexOf = mergeFields.indexOf(field);
            if (indexOf < 0) {
              // add
              masterSchema.addField(field, td.getChildren()
                                             .get(f));
            } else {
              // check type at some point...
            }
          }
        }
        return masterSchema;
    
      }
    
      private static void merge(Path testFilePath1, Configuration conf, Writer writer, VectorizedRowBatch writerBatch,
          TypeDescription masterSchema) throws IOException {
        Reader reader = OrcFile.createReader(testFilePath1, OrcFile.readerOptions(conf));
    
        int[] mapping = createMapping(masterSchema, reader.getSchema());
    
        try (RecordReader rows = reader.rows()) {
          VectorizedRowBatch readerBatch = reader.getSchema()
                                                 .createRowBatch();
          while (rows.nextBatch(readerBatch)) {
            for (int r = 0; r < readerBatch.size; ++r) {
              for (int c = 0; c < mapping.length; c++) {
                int index = mapping[c];
                if (index == -1) {
                  writerBatch.cols[c].isNull[writerBatch.size] = true;
                  writerBatch.cols[c].noNulls = false;
                } else {
                  writerBatch.cols[c] = readerBatch.cols[index];
                }
              }
              writerBatch.size++;
            }
            writer.addRowBatch(writerBatch);
            writerBatch.reset();
          }
        }
      }
    
      private static int[] createMapping(TypeDescription masterSchema, TypeDescription currentSchema) {
        List<String> masterFieldNames = masterSchema.getFieldNames();
        List<String> fieldNames = currentSchema.getFieldNames();
        int[] mappings = new int[masterFieldNames.size()];
        for (int f = 0; f < masterFieldNames.size(); f++) {
          String name = masterFieldNames.get(f);
          int indexOf = fieldNames.indexOf(name);
          if (indexOf < 0) {
            mappings[f] = -1;
          } else {
            mappings[f] = indexOf;
          }
        }
        return mappings;
      }
    
    }