Spark RDD- map vs mapPartitions

时间:2016-12-01 12:13:42

标签: java scala apache-spark garbage-collection

我阅读了map和mapPartitions之间的理论差异,&很清楚何时在各种情况下使用它们。

但我下面描述的问题更多是基于GC活动&内存(RAM)。请阅读下面的问题: -

=>我写了一个map函数来将Row转换为String。因此,RDD [org.apache.spark.sql.Row]的输入将映射到RDD [String]。但是使用这种方法,将为RDD的每一行创建地图对象。因此,创建如此大量的对象可能会增加GC活动。

=>为了解决上述问题,我想到了使用mapPartitions。因此,该对象的数量变得等于分区的数量。 mapPartitions将Iterator作为输入,并接受返回和java.lang.Iterable。但大多数Iterable,如Array,List等都在内存中。那么,如果我有大量数据,那么以这种方式创建Iterable会导致内存不足吗?或者是否有任何其他集合(java或scala)应该在这里使用(如果内存开始填充,溢出到磁盘)?或者我们应该只使用mapPartitions以防RDD完全在内存中?

提前致谢。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

如果您考虑JavaRDD.mapPartitions需要FlatMapFunction(或某些变体,例如DoubleFlatMapFunction),预计会返回Iterator而不是Iterable。如果收集的内容很懒,那么你就没什么可担心的了。

RDD.mapPartitionsIteratorIterator执行功能。

如果您使用参考数据,我可以将mapPartitions替换为map并使用静态成员来存储数据。这将具有相同的足迹,并且更容易编写。

答案 1 :(得分:1)

回答有关mapPartition(f:Iterator => Iterator)的问题。它是懒惰的,并且不将整个分区保存在mem中。 Spark将使用此(我们可以认为它是FP术语中的Functor)Iterator => Iterator函数,并将其重新编译为自己的代码以执行。如果分区太大,它将在下一个随机播放点之前溢出到磁盘。所以不用担心

需要提及的一件事是,您可以通过执行以下操作来强制函数将数据具体化为内存:

rdd.mapPartition(
  partitionIter => {
    partitionIter.map(do your logic).toList.toIterator
  }
)

toList将强制Spark将整个分区的数据具体化为mem,因此请注意这一点,因为toList之类的操作会破坏功能链的惰性。