Apache spark 随着分区的增长,spark拼花地板写入速度变慢

Apache spark 随着分区的增长,spark拼花地板写入速度变慢,apache-spark,partitioning,parquet,Apache Spark,Partitioning,Parquet,我有一个spark流应用程序,它从流中写入拼花地板数据 sqlContext.sql( """ |select |to_date(from_utc_timestamp(from_unixtime(at), 'US/Pacific')) as event_date, |hour(from_utc_timestamp(from_unixtime(at), 'US/Pacific')) as event_hour, |*

我有一个spark流应用程序,它从流中写入拼花地板数据

sqlContext.sql(
      """
        |select
        |to_date(from_utc_timestamp(from_unixtime(at), 'US/Pacific')) as event_date,
        |hour(from_utc_timestamp(from_unixtime(at), 'US/Pacific')) as event_hour,
        |*
        |from events
        | where at >= 1473667200
      """.stripMargin).coalesce(1).write.mode(SaveMode.Append).partitionBy("event_date", "event_hour","verb").parquet(Config.eventsS3Path)
这段代码每小时运行一次,但随着时间的推移,对拼花地板的写入速度变慢了。当我们开始写数据时需要15分钟,现在需要40分钟。与该路径中存在的数据相比,这需要一定的时间。我尝试将同一个应用程序运行到一个新位置,运行速度很快

我已禁用schemaMerge和摘要元数据:

sparkConf.set("spark.sql.hive.convertMetastoreParquet.mergeSchema","false")
sparkConf.set("parquet.enable.summary-metadata","false")
使用spark 2.0

批量执行: 空目录 包含350个文件夹的目录
我遇到了这个问题。追加模式可能是罪魁祸首,因为随着拼花地板文件大小的增加,查找追加位置需要越来越多的时间

我发现解决这个问题的一个解决方法是定期更改输出路径。合并和重新排序所有输出数据帧中的数据通常不是问题

def appendix: String = ((time.milliseconds - timeOrigin) / (3600 * 1000)).toString

df.write.mode(SaveMode.Append).format("parquet").save(s"${outputPath}-H$appendix")

这可能是由于附加模式。在这种模式下,新文件应该以不同于现有文件的名称生成,因此spark每次都会在s3中列出文件(速度较慢)

我们对parquet.enable.summary-metadata的设置也略有不同:

javaSparkContext.hadoopConfiguration().set("parquet.enable.summary-metadata", "false");

尝试将数据帧写入EMR HDFS(hdfs://...)然后使用s3 dist cp将数据从HDFS上传到s3。
为我工作。

我不明白为什么append会引起这样的问题?为什么append会有任何不同,它不像是在使用
append
时写入同一个文件,数据首先写入临时文件,然后如果成功,临时文件将复制到指定的outputPath中。这导致
Append
模式下的保存运行速度大大降低。但这并不能解释逐渐增长的原因,从临时目录移动到正确目录是一项固定成本。所以我应该看到第二次迭代本身的成本。相反,我看到它随着时间的推移逐渐增长。添加了dag以了解更多详细信息,但在300个目录中列出10分钟(两次)仍然很困难large@GauravShah,尝试使用aws s3列出相同的目录--从同一台计算机递归。DAG的问题是,它没有必要显示spark所做的一切(例如,我100%知道,当你有很多文件附加到s3时,提交阶段需要很多时间,它是驱动程序的单线程,但你在spark ui中看不到这一点,所有任务/作业都完成了)@Gauravsha,注意我的编辑,parquet.enable.summary-metadata是hadoop属性,而不是spark属性。spark 2中默认禁用它,它将尝试这样做。它也可以只列出它正在写入的目录中的文件,而不是从所有目录中列出,如果只是检查文件是否存在,问题是因为spark尝试列出所有叶节点,而这部分速度非常慢,它尝试了两次,总共增加了13*2分钟。虽然我无法找出列表文件速度慢的原因,但您是否找到了解决方案?我遇到了同样的问题。在spark submit stderr中,我可以看到spark在S3中打开用于阅读和查找旧拼花文件。我只是不知道如何避免这种情况。我无法避免读取旧分区,但我确实将分区读取速度提高了10倍。通过将所有时间从10分钟减少到1分钟,您认为如何将新数据写入本地HDF,然后将其复制到s3?这样的话,列表将是快速的。每次调用MVP时,不妨复制到s3上的一个新位置。您没有回答问题tho。没有问题,OP只是描述了一个问题,我建议了一个解决方案。Netflix也做了同样的IIRC(即首先写入HDFS,而不是复制到S3)。