我使用下一个代码:
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结果文件?
答案 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