一、map 操作 V.S. mappartition 操作

  • map 操作:对 RDD 中的每个元素进行操作(可以理解为遍历),比如使用一个function则需要执行该 function n 次,其中 n 为元素个数;
  • mappartition 操作:对 RDD 中每个 partition 的 iterator 进行操作,比如使用一个 function 则每个 partition 只需要各执行该 function 1 次(一个partition中的所有元素被一次传给该 function);

因此,存在如下结论:

  1. map 操作: 执行 1 次 function 只处理 1 个元素(或者称为一条数据),比如 partition 中的元素较多,当前已经处理了 1000 个元素,在内存不足的情况下,Spark 可以通过GC等方法(比如将已处理掉的 1000 个元素从内存中回收)回收内存。因此,通常 map 操作不会导致OOM的异常;
  2. mappartition 操作: 执行 1 次 function 需要接收该 partition 中的所有元素,因此一旦元素很多而处理内存不足,就容易导致OOM的异常
  3. 一般而言,mappartition 的性能更高;初始化操作、数据库访问等操作适合使用 mappartition操作,这是因为:
    • 假设需要对 RDD 中的每个元素做加密计算,在加密之前需要在每个 executor 中执行 initialization 操作,试想一下,如果该 initialization 放在 map 中执行将会导致该 initialization 被执行很多次,非常耗时;但是如果放在 mappartition 中则只需要每个 executor 中执行 1 次即可;
    • 假设需要将 RDD 中的每个元素写入数据库中,这时候就应该把创建数据库的链接connection 操作放置在 mappartition 中,访问数据库操作本身就是个比较耗时的任务,如果该操作放在 map 中执行将会非常耗时且影响数据库的稳定。

二、foreach 操作 V.S. foreachpartition 操作

map 和 foreach 的区别在于:

  • 前者是 transformation 操作(不会立即执行),后者是 action 操作(会立即执行);
  • 前者返回值是一个新 RDD,后者没有返回值。

其他的和 map V.S. mappartition 类似。

Scala中的集合对象都有foreach和map两个方法。两个方法的共同点在于:都是用于遍历集合对象,并对每一项执行指定的方法。而两者的差异在于:foreach无返回值(准确说返回void),map返回集合对象。结论就是:foreach 无法代替map. 而map方法却可以代替foreach。

问题:为什么scala提供foreach和map两个方法呢?本人看法是scala做为一种支持函数式编程范式的语言,必然要引入一种机制以支持数学中函数概念,而在数学中函数就是映射,所以scala中有map方法一点都不奇怪。而foreach只是用在不需要对集合执行映射操作,但需要遍历集合时才用到。总而言之,foreach用于遍历集合,而map用于映射(转换)集合到另一个集合



作者:alexlee666
链接:https://www.jianshu.com/p/0f2d47bd820d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐