1.小分区合并问题
在用户使用Spark的过程中,常常会使用filter算子进行数据过滤。而频繁的过滤或者过滤掉的数据量过大就会产生问题,造成大量小分区的产生(每个分区数据量小)。由于Spark是每个数据分区都会分配一个任务执行,如果任务过多,则每个任务处理的数据量很小,会造成线程切换开销大,很多任务等待执行,并行度不高的问题,是很不经济的。
例如:
val rdd2 = rdd1.filter(line=>lines.contains("error"
)).filter(line=>line.contains(info).collect();
解决方式:可以采用RDD中重分区的函数进行数据紧缩,减少分区数,将小分区合并变为大分区。通过coalesce函数来减少分区,具体如下。
def coalesce(numPartitions: Int, shuffle: Boolean = false)(implicit
ord: Ordering[T] = null): RDD[T]
这个函数会返回一个含有numPartitions数量个分区的新RDD,即将整个RDD重分区。以下几个情景请大家注意,当分区由10000重分区到100时,由于前后两个阶段的分区是窄依赖的,所以不会产生Shuffle的操作。但是如果分区数量急剧减少,如极端状况从10000重分区为一个分区时,就会造成一个问题:数据会分布到一个节点上进行计算,完全无法开掘集群并行计算的能力。为了规避这个问题,可以设置shuffle=true。请看源码:
new CoalescedRDD(newShuffledRDD[Int, T, T, (Int,T)]
(mapPartitionsWithIndex(distribut