当前位置: 首页 > news >正文

Spark Rdd coalesce()方法和repartition()方法

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

在Spark的Rdd中,Rdd是分区的。

有时候需要重新设置Rdd的分区数量,比如Rdd的分区中,Rdd分区比较多,但是每个Rdd的数据量比较小,需要设置一个比较合理的分区。或者需要把Rdd的分区数量调大。还有就是通过设置一个Rdd的分区来达到设置生成的文件的数量。

有两种方法是可以重设Rdd的分区:分别是 coalesce()方法和repartition()。

 这两个方法有什么区别,看看源码就知道了:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

def coalesce(numPartitions: Int, shuffle: Boolean = false)(implicit ord: Ordering[T] = null)

    : RDD[T] = withScope {

  if (shuffle) {

    /** Distributes elements evenly across output partitions, starting from a random partition. */

    val distributePartition = (index: Int, items: Iterator[T]) => {

      var position = (new Random(index)).nextInt(numPartitions)

      items.map { t =>

        // Note that the hash code of the key will just be the key itself. The HashPartitioner

        // will mod it with the number of total partitions.

        position = position + 1

        (position, t)

      }

    } : Iterator[(Int, T)]

 

    // include a shuffle step so that our upstream tasks are still distributed

    new CoalescedRDD(

      new ShuffledRDD[Int, T, T](mapPartitionsWithIndex(distributePartition),

      new HashPartitioner(numPartitions)),

      numPartitions).values

  } else {

    new CoalescedRDD(this, numPartitions)

  }

}

coalesce()方法的作用是返回指定一个新的指定分区的Rdd。

如果是生成一个窄依赖的结果,那么不会发生shuffle。比如:1000个分区被重新设置成10个分区,这样不会发生shuffle。

关于Rdd的依赖,这里提一下。Rdd的依赖分为两种:窄依赖和宽依赖。

窄依赖是指父Rdd的分区最多只能被一个子Rdd的分区所引用,即一个父Rdd的分区对应一个子Rdd的分区,或者多个父Rdd的分区对应一个子Rdd的分区。

而宽依赖就是宽依赖是指子RDD的分区依赖于父RDD的多个分区或所有分区,即存在一个父RDD的一个分区对应一个子RDD的多个分区。1个父 RDD分区对应多个子RDD分区,这其中又分两种情况:1个父RDD对应所有子RDD分区(未经协同划分的Join)或者1个父RDD对应非全部的多个 RDD分区(如groupByKey)。

如下图所示:map就是一种窄依赖,而join则会导致宽依赖

回到刚才的分区,如果分区的数量发生激烈的变化,如设置numPartitions = 1,这可能会造成运行计算的节点比你想象的要少,为了避免这个情况,可以设置shuffle=true,

那么这会增加shuffle操作。

关于这个分区的激烈的变化情况,比如分区数量从父Rdd的几千个分区设置成几个,有可能会遇到这么一个错误。

复制代码

Exception in thread "main" org.apache.spark.SparkException: Job aborted due to stage failure: Task 1 in stage 77.0 failed 4 times, most recent failure: Lost task 1.3 in stage 77.0 (TID 6334, 192.168.8.61): java.io.IOException: Unable to acquire 16777216 bytes of memory
        at org.apache.spark.util.collection.unsafe.sort.UnsafeExternalSorter.acquireNewPage(UnsafeExternalSorter.java:351)
        at org.apache.spark.util.collection.unsafe.sort.UnsafeExternalSorter.acquireNewPageIfNecessary(UnsafeExternalSorter.java:332)
        at org.apache.spark.util.collection.unsafe.sort.UnsafeExternalSorter.insertKVRecord(UnsafeExternalSorter.java:461)
        at org.apache.spark.sql.execution.UnsafeKVExternalSorter.insertKV(UnsafeKVExternalSorter.java:139)
        at org.apache.spark.sql.execution.aggregate.TungstenAggregationIterator.switchToSortBasedAggregation(TungstenAggregationIterator.scala:489)
        at org.apache.spark.sql.execution.aggregate.TungstenAggregationIterator.processInputs(TungstenAggregationIterator.scala:379)
        at org.apache.spark.sql.execution.aggregate.TungstenAggregationIterator.start(TungstenAggregationIterator.scala:622)
        at org.apache.spark.sql.execution.aggregate.TungstenAggregate$$anonfun$doExecute$1.org$apache$spark$sql$execution$aggregate$TungstenAggregate$$anonfun$$executePartition$1(TungstenAggregate.scala:110)
        at org.apache.spark.sql.execution.aggregate.TungstenAggregate$$anonfun$doExecute$1$$anonfun$2.apply(TungstenAggregate.scala:119)
        at org.apache.spark.sql.execution.aggregate.TungstenAggregate$$anonfun$doExecute$1$$anonfun$2.apply(TungstenAggregate.scala:119)
        at org.apache.spark.rdd.MapPartitionsWithPreparationRDD.compute(MapPartitionsWithPreparationRDD.scala:64)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.MapPartitionsWithPreparationRDD.compute(MapPartitionsWithPreparationRDD.scala:63)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.MapPartitionsWithPreparationRDD.compute(MapPartitionsWithPreparationRDD.scala:63)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.ZippedPartitionsRDD2.compute(ZippedPartitionsRDD.scala:99)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.UnionRDD.compute(UnionRDD.scala:87)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:300)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
        at org.apache.spark.rdd.CoalescedRDD$$anonfun$compute$1.apply(CoalescedRDD.scala:96)
        at org.apache.spark.rdd.CoalescedRDD$$anonfun$compute$1.apply(CoalescedRDD.scala:95)
        at scala.collection.Iterator$$anon$13.hasNext(Iterator.scala:371)
        at org.apache.spark.util.collection.ExternalSorter.insertAll(ExternalSorter.scala:209)
        at org.apache.spark.shuffle.sort.SortShuffleWriter.write(SortShuffleWriter.scala:73)
        at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:73)
        at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:41)
        at org.apache.spark.scheduler.Task.run(Task.scala:88)
        at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:214)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)

复制代码

这个错误只要把shuffle设置成true即可解决。

当把父Rdd的分区数量增大时,比如Rdd的分区是100,设置成1000,如果shuffle为false,并不会起作用。

这时候就需要设置shuffle为true了,那么Rdd将在shuffle之后返回一个1000个分区的Rdd,数据分区方式默认是采用 hash partitioner。

最后来看看repartition()方法的源码:

def repartition(numPartitions: Int)(implicit ord: Ordering[T] = null): RDD[T] = withScope {
    coalesce(numPartitions, shuffle = true)
  }

从源码可以看出,repartition()方法就是coalesce()方法shuffle为true的情况。那么如果说只是要减少父Rdd的分区数量,并且要设置的分区数量并不是很激烈,可以考虑直接使用coalesce方法来避免执行shuffle操作,提高效率。

如有错误遗漏的地方,请不吝赐教,我必将改正。

转载于:https://my.oschina.net/sniperLi/blog/713663

相关文章:

  • 基于Oracle的SQL优化--学习(一)
  • 基于Oracle的SQL优化--学习(二)
  • MySQL案例-show fileds from 提示无权限
  • B+树的数据结构理解
  • 基于Oracle的SQL优化--学习(三)
  • 打 spice 的 deb 格式安装包的时遇到的问题和解决方法
  • 基于Oracle的SQL优化--学习(四)
  • 基于Oracle的SQL优化--学习(五)
  • 基于Oracle的SQL优化--学习(六)
  • (转载)hibernate缓存
  • 基于Oracle的SQL优化--学习(七)
  • 基于Oracle的SQL优化--学习(八)
  • MySQL数字类型中的三种常用种类【转】
  • linux mmap 内存映射【转】
  • 基于Oracle的SQL优化--学习(九)
  • __proto__ 和 prototype的关系
  • 【mysql】环境安装、服务启动、密码设置
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • C++类的相互关联
  • co模块的前端实现
  • Cumulo 的 ClojureScript 模块已经成型
  • eclipse(luna)创建web工程
  • emacs初体验
  • ES2017异步函数现已正式可用
  • ES6 ...操作符
  • ES6简单总结(搭配简单的讲解和小案例)
  • Iterator 和 for...of 循环
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • mysql innodb 索引使用指南
  • Phpstorm怎样批量删除空行?
  • Redux系列x:源码分析
  • SOFAMosn配置模型
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • WePY 在小程序性能调优上做出的探究
  • Yeoman_Bower_Grunt
  • 阿里云ubuntu14.04 Nginx反向代理Nodejs
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • - 概述 - 《设计模式(极简c++版)》
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 理解在java “”i=i++;”所发生的事情
  • 力扣(LeetCode)22
  • 移动端唤起键盘时取消position:fixed定位
  • #{}和${}的区别?
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • $$$$GB2312-80区位编码表$$$$
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (6)设计一个TimeMap
  • (poj1.3.2)1791(构造法模拟)
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • .bashrc在哪里,alias妙用
  • @Autowired注解的实现原理
  • [ C++ ] STL---仿函数与priority_queue
  • [] 与 [[]], -gt 与 > 的比较
  • [20140403]查询是否产生日志