【问题标题】:How to split a big Sequence file into multiple sequence files?如何将一个大的序列文件拆分为多个序列文件?
【发布时间】:2017-10-01 07:46:13
【问题描述】:

我有一个包含大约 6000 万个条目(将近 4.5GB)的大型序列文件。 我想拆分它。例如,我想把它分成三部分,每部分有 2000 万个条目。到目前为止我的代码是这样的:

//Read from sequence file
  JavaPairRDD<IntWritable,VectorWritable> seqVectors = sc.sequenceFile(inputPath, IntWritable.class, VectorWritable.class);
  JavaPairRDD<IntWritable,VectorWritable> part=seqVectors.coalesce(3);
  part.saveAsHadoopFile(outputPath+File.separator+"output", IntWritable.class, VectorWritable.class, SequenceFileOutputFormat.class);

但不幸的是,每个生成的序列文件也都在 4GB 左右(总共 12GB)! 任何人都可以提出更好/有效的方法吗?

【问题讨论】:

  • 你所做的就是去恕我直言。如果您希望文件具有相同大小,请使用重新分区而不是合并
  • 但重新分区给出了错误--> 03 年 17 月 5 日 23:10:46 错误 executor.Executor: 阶段 0.0 (TID 1) 中任务 1.0 中的异常 com.esotericsoftware.kryo.KryoException :java.util.ConcurrentModificationException 序列化跟踪:类(sun.misc.Launcher$AppClassLoader)classLoader(org.apache.hadoop.mapred.JobConf)conf(org.apache.mahout.math.VectorWritable)----详细跟踪- --> pastebin.com/eDWvV6Fx@TalJoffe
  • 我认为问题在于洗牌,因为如果我使用 coalesce(3,true) 会抛出同样的问题!
  • 如果您的 RDD 中的对象不可序列化,则可能...您可以尝试使它们可序列化,或者另一种选择是将 RDD 转换为 Dataframe,然后进行重新分区

标签: java apache-spark rdd sequencefile bigdata


【解决方案1】:

也许不是您正在寻找的确切答案,但可能值得尝试阅读the second method for sequenceFile,它需要一个 minPartitions 参数。请记住,您正在使用的coalesce 只能减少分区。

您的代码应如下所示:

//Read from sequence file
JavaPairRDD<IntWritable,VectorWritable> seqVectors = sc.sequenceFile(inputPath, IntWritable.class, VectorWritable.class, 3);
seqVectors.saveAsHadoopFile(outputPath+File.separator+"output", IntWritable.class, VectorWritable.class, SequenceFileOutputFormat.class);

另一件可能导致问题的事情是某些序列文件是不可拆分的。

【讨论】:

    【解决方案2】:

    也许我没有正确理解您的问题,但为什么不逐行读取您的文件(=逐个条目?)并以这种方式构建您的三个文件? 应该是这样的:

    int i = 0;
    List<PrintWriter> files = new ArrayList<PrintWriter>();
    files.add(new PrintWriter("the-file-name1.txt", "UTF-8"));
    files.add(new PrintWriter("the-file-name2.txt", "UTF-8"));
    files.add(new PrintWriter("the-file-name3.txt", "UTF-8"));
    for String line in Files.readAllLines(Paths.get(fileName)){
      files.get(i % 3).writeln(line);
      i++;
    }
    

    在这种情况下,每三行一行进入第一个、第二个和第三个文件。

    如果文件不是文本文件,另一种解决方案是进行二进制读取,使用 Files.readAllBytes(Paths.get(inputFileName)) 并使用 Files.write(Paths.get(output1), byteToWrite) 写入输出文件。

    但是,我不知道为什么输出在您的操作方式中占据了如此多的位置。也许编码是有罪的?我认为 java 默认使用 UTF-8 编码,您的输入文件可能使用 ASCII 编码。

    【讨论】:

    • 它不是一个文本文件,它是一个序列文件。对于文本文件,我可以轻松地做到这一点,我也可以对我认为的序列文件采取逐行方法,但我正在寻找从 spark rdd 角度来看的最佳方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 2022-01-16
    • 2017-01-27
    • 2015-08-01
    相关资源
    最近更新 更多