因此问题在此。我认为我不正确理解重新分区的工作。在我的脑海中,当我说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。
当我不进行分区时,一切都很好。我不明白分区正确的地方?
答案 0 :(得分:1)
您的逻辑对于repartition
和partitionBy
都是正确的,但是在使用repartition
之前,您需要牢记来自多个方面的知识。
请记住,重新分区数据是相当昂贵的 操作。 Spark还具有称为repartition()的优化版本。 Coalesce()允许避免数据移动,但前提是您必须 减少RDD分区的数量。
如果您希望必须完成任务,请增加驱动程序和执行程序的存储空间