1. 说明
/*
* 1. 定义
* def coalesce(numPartitions: Int
* , shuffle: Boolean = false
* , partitionCoalescer: Option[PartitionCoalescer] = Option.empty)
* (implicit ord: Ordering[T] = null)
* : RDD[T]
* numPartitions : 指定分区个数
* shuffle : 是否需要shuffle(默认为false)
*
* 2. 功能
* 调整Rdd的分区个数(变大\变小),改变分区时,可以选择是否Shuffle
* shffle=true,分区可以变大或者变小
* shuffle=false,分区是能变小(变大不生效)
*
* 3. note
* 1.不shuffle 即 shuffle = false
* 分区数变大时,如父rdd 10分区,子rdd 100分区
* 通过 rdd.coalesce(100) 处理后,子rdd分区数已然是10,不会变大
* 分区数变小时,如父rdd 1000分区,子rdd 100分区
* 通过 rdd.coalesce(100),子rdd 会合并
*
* 2.shuffle 即 shuffle = true
* 无论分区变大还是变小,数据都会被分配到每个分区
*
* 4. 使用场景
* 当spark任务中分区数过多时(即每个Task处理数据量不大),此时存在过多的小任务,Task的启动和调度都会
* 消耗时间,此时可以对分区进行合并,来减少Task的数量,从而减小任务调度的开销
*
* */
/* coalesce 算子 */
object RddTransitionOperator_coalesce extends App {
private val sc: SparkContext = CommonUtils.getSparkContext("groupBy distinct")
private val rdd: RDD[Long] = sc.range(1, 10, 1, 4)
private val rdd2: RDD[Long] = rdd.coalesce(5, false)
println(s"分区数:${rdd2.getNumPartitions}")
println(s"rdd类型:${rdd2.getClass.getName}")
// 分区数:2
// rdd类型:org.apache.spark.rdd.CoalescedRDD
rdd2.collect().foreach(println(_))
rdd2.saveAsTextFile("src/main/data/output/listrdd9")
private val rdd3: RDD[Long] = rdd.coalesce(6, true)
println(s"分区数:${rdd3.getNumPartitions}")
println(s"rdd类型:${rdd3.getClass.getName}")
// 分区数:2
// rdd类型:org.apache.spark.rdd.MapPartitionsRDD
//rdd3.collect()
//rdd3.saveAsTextFile("src/main/data/output/listrdd7")
//sc.stop()
while (true) {}
}
2. 缩小(合并)分区
object coalesceTest extends App {
//缩小(合并)分区
/*
* 1. shuffle Vs No Shuffle
* shuffle : 会使用分区器,对元素重新分区,均衡的分发到分区内
* No Shuffle : 只是 简单的对某几个分区进行 合并操作(可能造成 数据倾斜)
*
* 2. note
* 合并分区时,尽量shuffle
*
* 3. 示例-No Shuffle
* rdd
* part-00000 : 1, 2, 3
* part-00001 : 4, 5, 6
* part-00002 : 7, 8, 9
* rdd1(数据分布不均)
* part-00000 : 1, 2, 3
* part-00001 : 4, 5, 6, 7, 8, 9
*
* 3. 示例-Shuffle
* rdd
* part-00000 : 1, 2, 3
* part-00001 : 4, 5, 6
* part-00002 : 7, 8, 9
* rdd1(数据分布均衡)
* part-00000 : 1, 3, 5, 7, 9
* part-00001 : 2, 4, 6, 8
*
* */
val sparkconf: SparkConf = new SparkConf().setMaster("local").setAppName("distinctTest")
val sc: SparkContext = new SparkContext(sparkconf)
val rdd = sc.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9), 3)
//rdd.saveAsTextFile("Spark_319/src/output/01")
private val rdd1: RDD[Int] = rdd.coalesce(2,true)
rdd1.saveAsTextFile("Spark_319/src/output/02")
println(s"当前分区数 : ${rdd1.getNumPartitions}")
println(rdd1.collect().mkString(","))
sc.stop()
}
3. 扩大分区
object coalesceTest extends App {
//扩大分区
/*
* 1. shuffle Vs No Shuffle
* shuffle : 会使用分区器,对元素重新分区,均衡的分发到分区内
* No Shuffle : 不会生效
*
* 2. note
* 扩大分区时,如果不shuflle,将不会生效
* coalesce(numPartitions, shuffle = true) = repartition(numPartitions)
*
* */
val sparkconf: SparkConf = new SparkConf().setMaster("local").setAppName("distinctTest")
val sc: SparkContext = new SparkContext(sparkconf)
val rdd = sc.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9), 1)
//rdd.saveAsTextFile("Spark_319/src/output/01")
private val rdd1: RDD[Int] = rdd.coalesce(2, true)
private val rdd2: RDD[Int] = rdd.repartition(2)
rdd1.saveAsTextFile("Spark_319/src/output/02")
rdd1.saveAsTextFile("Spark_319/src/output/03")
println(s"当前分区数 : ${rdd1.getNumPartitions}")
println(rdd1.collect().mkString(","))
sc.stop()
}