读取多个文件时,Spark驱动程序的内存不足

时间:2018-07-09 14:29:48

标签: apache-spark dataframe apache-spark-sql out-of-memory multiple-files

我的程序如下:

  1. 读取许多文件作为数据框。在这些文件中,大约有60个文件,每个组有5k行,在其中我为每个文件创建一个单独的数据框,进行一些简单的处理,然后将它们合并为一个数据框,用于进一步加入。
  2. 我最终对多个数据框执行了许多联接和列计算,最终得到了目标数据框。
  3. 我将目标数据帧另存为Parquet文件。
  4. 在同一个spark应用程序中,我加载了该Parquet文件并进行了一些繁重的聚合,然后对该数据帧进行了多个自联接。
  5. 我将第二个数据帧另存为另一个Parquet文件。

问题

如果我只有一个文件而不是上面提到的文件组中的60个文件,那么一切都可以在具有8g内存的驱动程序中使用。对于60个文件,前三个步骤可以正常工作,但是在准备第二个文件时驱动程序会用尽内存。仅当我将驱动程序的内存增加到20g时,情况才会改善。

问题

那是为什么?在计算第二个文件时,我不使用用于计算第一个文件的数据框,因此,如果第一个Parquet文件的大小保持不变,它们的数量和内容就没有什么关系了吗?那60个数据帧是否以某种方式被缓存并占用了驱动程序的内存?我自己不缓存。我也从不收集任何东西。我不明白为什么8g的内存不足以支持Spark驱动程序。

2 个答案:

答案 0 :(得分:0)

缓存或持久性是用于(迭代和交互式)Spark计算的优化技术。它们有助于保存临时的部分结果,以便可以在后续阶段中重复使用。因此,将RDD的这些临时结果保存在内存中(默认值)或更多的固态存储(如磁盘)和/或已复制。 可以使用缓存操作来缓存RDD。也可以使用持久操作来持久化它们。 缓存和持久操作之间的区别纯粹是语法上的。缓存是persist或persist(MEMORY_ONLY)的同义词,即缓存仅使用默认存储级别MEMORY_ONLY进行持久化。

参阅use of persist and unpersist

答案 1 :(得分:0)

conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
//you have to use serialization configuration if you are using MEMORY_AND_DISK_SER 


val rdd1 = sc.textFile("some data")
rdd1.persist(storageLevel.MEMORY_AND_DISK_SER)   // marks rdd as persist
val rdd2 = rdd1.filter(...)
val rdd3 = rdd1.map(...)

rdd2.persist(storageLevel.MEMORY_AND_DISK_SER)
rdd3.persist(storageLevel.MEMORY_AND_DISK_SER)

rdd2.saveAsTextFile("...")
rdd3.saveAsTextFile("...")

rdd1.unpersist()
rdd2.unpersist()
rdd3.unpersist()

要调整代码,请遵循以下link