繁体   English   中英

Spark RDD- map与mapPartitions

[英]Spark RDD- map vs mapPartitions

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

但是我下面描述的问题更多地取决于GC活动和内存(RAM)。 有关问题,请阅读以下内容:

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

=>要解决以上问题,我想到了使用mapPartitions。 因此,该对象数等于分区数。 mapPartitions提供Iterator作为输入,并接受return和java.lang.Iterable。 但是大多数Iterable(例如Array,List等)都在内存中。 那么,如果我有大量数据,那么以这种方式创建Iterable会导致内存不足吗? 还是在这里应该使用其他任何集合(java或scala)(以防万一内存开始填充到磁盘上)? 还是仅在RDD完全在内存中的情况下才使用mapPartitions?

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

如果您考虑使用JavaRDD.mapPartitions则需要使用FlatMapFunction (或某些类似DoubleFlatMapFunction变体),该函数将返回Iterator not Iterable 如果底层收集很懒,那么您就不用担心。

RDD.mapPartitions接受从IteratorIterator的函数。

通常,如果您使用参考数据,则可以用map替换mapPartitions并使用静态成员来存储数据。 这将具有相同的占用空间,并且更易于编写。

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

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

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

toList将强制Spark将整个分区的数据具体化为mem,因此请注意这一点,因为类似于toList ops将打破功能链的惰性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM