如何在没有重新分区和copyMerge的情况下合并spark结果文件?

时间:2015-03-13 04:57:10

标签: scala hadoop apache-spark

我使用下一个代码:

csv.saveAsTextFile(pathToResults, classOf[GzipCodec])

pathToResults目录有很多文件,如part-0000,part-0001等。 我可以使用FileUtil.copyMerge(),但它真的很慢,它会下载驱动程序上的所有文件,然后将它们上传到hadoop。但FileUtil.copyMerge()比:

更快
csv.repartition(1).saveAsTextFile(pathToResults, classOf[GzipCodec])

如何在没有重新分区和FileUtil.copyMerge()的情况下合并spark结果文件?

3 个答案:

答案 0 :(得分:8)

不幸的是,没有其他选项可以在Spark中获取单个输出文件。您可以使用repartition(1)代替coalesce(1),但使用参数1,他们的行为将是相同的。 Spark会在内存中的单个分区中收集您的数据,如果您的数据太大,可能会导致OOM错误。

在HDFS上合并文件的另一个选择可能是编写一个简单的MapReduce作业(或Pig作业或Hadoop Streaming作业),它将整个目录作为输入,并使用单个reducer生成单个输出文件。但请注意,使用MapReduce方法,所有数据都将首先复制到reducer本地文件系统,这可能会导致空间超出空间"错误。

以下是关于同一主题的一些有用链接:

答案 1 :(得分:0)

有完全相同的问题,并且必须编写实现copyMerge的pySpark代码(调用Hadoop API):

https://github.com/Tagar/stuff/blob/master/copyMerge.py

不幸的是,作为独立的Hadoop API调用的copyMerge将在Hadoop 3.0中被弃用和删除。所以这个实现并不依赖于Hadoop的copyMerge(它重新实现它)。

答案 2 :(得分:0)

coalesce(1)运行正常。我还看到了hadoop-streaming选项,如果您想运行此脚本,可以动态合并HDFS文件:

$ hadoop jar /usr/hdp/2.3.2.0-2950/hadoop-mapreduce/hadoop-streaming-2.7.1.2.3.2.0-2950.jar \
                   -Dmapred.reduce.tasks=1 \
                   -input "/hdfs/input/dir" \
                   -output "/hdfs/output/dir" \
                   -mapper cat \
                   -reducer cat