为什么Spark重新分区会导致MemoryOverhead?

时间:2018-06-28 04:40:16

标签: scala apache-spark partitioning

因此问题在此。我认为我不正确理解重新分区的工作。在我的脑海中,当我说somedataset.repartition(600)时,我希望所有数据(例如60个工作人员)的大小均相等。

例如。我要在不平衡文件中加载大量数据,可以说400个文件,其中20%是2Gb大小,其他80%是1 Mb。我有加载此数据的代码:

val source = sparkSession.read.format("com.databricks.spark.csv")
  .option("header", "false")
  .option("delimiter","\t")
  .load(mypath)

比起我想将原始数据转换为中间对象,过滤不相关的记录,转换为最终对象(具有附加属性),然后按某些列进行分区并写入镶木地板。在我看来,在各个工作人员之间平衡数据(40000个分区)似乎是合理的,而不是像这样进行工作:

val ds: Dataset[FinalObject] = source.repartition(600)
  .map(parse)
  .filter(filter.IsValid(_))
  .map(convert)
  .persist(StorageLevel.DISK_ONLY)
val count = ds.count
log(count)
val partitionColumns = List("region", "year", "month", "day")

ds.repartition(partitionColumns.map(new org.apache.spark.sql.Column(_)):_*)
  .write.partitionBy(partitionColumns:_*)
  .format("parquet")
  .mode(SaveMode.Append)
  .save(destUrl)

但是失败

  

ExecutorLostFailure(执行程序7退出,原因之一是正在运行   任务)原因:容器因超出内存限制而被YARN杀死。   34.6 GB的34.3 GB物理内存。考虑提高spark.yarn.executor.memoryOverhead。

当我不进行分区时,一切都很好。我不明白分区正确的地方?

1 个答案:

答案 0 :(得分:1)

您的逻辑对于repartitionpartitionBy都是正确的,但是在使用repartition之前,您需要牢记来自多个方面的知识。

  

请记住,重新分区数据是相当昂贵的   操作。 Spark还具有称为repartition()的优化版本。   Coalesce()允许避免数据移动,但前提是您必须   减少RDD分区的数量。

如果您希望必须完成任务,请增加驱动程序和执行程序的存储空间