通过使用Pyspark在S3上保存数据集时花费的时间太长

时间:2019-06-07 14:37:03

标签: python apache-spark amazon-s3 pyspark amazon-emr

我正在尝试使用pyspark在S3上使用partitionBy保存数据集。我在日期列上进行分区。 Spark作业要花费超过一个小时才能执行。如果我在不使用partitionBy的情况下运行代码,则只需3-4分钟。 有人可以帮我微调声调吗?

2 个答案:

答案 0 :(得分:0)

好的,所以执行IO时spark很糟糕。特别是对于s3。当前,当您编写Spark时,它将使用整个执行程序依次写入数据。在s3和spark之间来回移动会导致它非常缓慢。因此,您可以采取一些措施来缓解/避免这些问题。

  • 如有可能,请使用其他分区策略,目标是最大程度地减少写入的文件。
  • 如果在写入之前涉及随机播放,则可以更改默认随机播放大小spark.sql.shuffle.partitions 200 // 200 is the default you'll probably want to reduce this周围的设置,并且/或者在写入之前重新分区数据。
  • 您可以绕过sparks io并编写自己的hdfs writer或直接使用s3 api。使用foreachpartition之类的函数,然后编写s3的函数。这样,事情将并行而不是顺序地写。
  • 最后,在编写(DataFrame partitionBy to a single Parquet file (per partition))时,您可能希望同时使用repartition和partitionBy。与上面的maxRecordsPerFile(如下)混合使用时,这将导致每个分区一个文件。这将有助于减小文件大小。

请注意:您可以使用选项spark.sql.files.maxRecordsPerFile 1000000帮助控制文件大小,以确保文件不会失控。

简而言之,您应该避免创建太多文件,尤其是小的文件。另外请注意:当您重新读取这些2000 * n文件时,也会发现性能受到很大的影响。

我们在不同情况下使用上述所有策略。但是通常,我们只是尝试在写入之前使用合理的分区策略+重新分区。另一个注意事项:如果执行随机播放,则分区将被破坏并触发自动分区。因此,需要不断进行重新分区。

希望这些建议对您有所帮助。 SparkIO非常令人沮丧,但是只要记住将文件的读写保持在最低水平,您应该会看到良好的性能。

答案 1 :(得分:0)

使用版本2的 FileOutputCommiter

.set("mapreduce.fileoutputcommitter.algorithm.version", "2")