【问题标题】:Should we avoid partitionBy when writing files to S3 in spark?在 Spark 中将文件写入 S3 时我们应该避免 partitionBy 吗?
【发布时间】:2020-05-02 05:45:58
【问题描述】:

拼花位置是:

s3://mybucket/ref_id/date/camera_id/parquet-file

假设我有ref_id x3、date x 4、camera_id x 500,如果我像下面这样写拼花地板(使用partitionBy),我会得到3x4x500=6000 文件上传到S3。比只写几个文件到顶层bucket(没有多级前缀)要慢得多

最佳做法是什么?我的同事认为partitionBy 与 Hive 元存储/表一起使用是一件好事

df.write.mode("overwrite")\
  .partitionBy('ref_id','date','camera_id')\
  .parquet('s3a://mybucket/tmp/test_data')

【问题讨论】:

  • 曾经遇到过这个问题,最终将最大分区数固定为 2...如果您使用的是 EMR,您可以先写入本地 HDFS,然后将数据复制到 S3。也尝试设置spark.hadooop.mapreduce.fileoutputcommitter.algorithm.version=2 以提高性能。
  • @blackbishop commit version=2 已应用

标签: scala apache-spark amazon-s3 apache-spark-sql parquet


【解决方案1】:

如果您的问题是文件过多(似乎是这种情况),您需要在编写 RDD/dataframe 之前对其进行重新分区。每个 RDD/Dataframe 分区将为每个文件夹生成 1 个文件。

df.repartition(1)\
 .write.mode("overwrite")\
 .partitionBy('ref_id','date','camera_id')\
 .parquet('s3a://mybucket/tmp/test_data')

除了repartition,您还可以使用coalesce


如果(重新分区为1后)文件太小了,需要减少目录结构。 parquet 文档建议文件大小在 500Mb 和 1Gb 之间。

https://parquet.apache.org/documentation/latest/

我们建议使用大型行组 (512MB - 1GB)。由于整行 可能需要读取组,我们希望它完全适合一个 HDFS 块。

如果你的文件只有几 Kb 或 Mb,那么你就有一个严重的问题,它会严重影响性能。

【讨论】:

  • 即使每个文件夹1个文件仍然太多(3x4x500=6000个文件),我的意思是,不要使用多级/前缀?
  • 如果每个文件夹 1 个文件太多,那么您的文件夹太多。每个partitionBy 都会生成一个文件夹级别。如果文件太小,则文件夹数量会减少,因为这会影响性能。
  • @thebluephantom 这将取决于您的数据大小。在他的情况下,即使每个文件夹有 1 个文件,他仍然以非常小的文件结束
猜你喜欢
  • 1970-01-01
  • 2020-05-28
  • 2012-10-14
  • 2018-10-26
  • 2019-05-01
  • 1970-01-01
  • 2023-04-03
  • 2018-06-16
  • 1970-01-01
相关资源
最近更新 更多