page59,关于groupByKey在不同partitoner时的shuffle问题
zdkzdk opened this issue · comments
1.你说groupByKey在左右2个算子的partitioner相同时不会进行shuffle,这里的partitioner相同应该怎么理解。应该是分区器的类型和分区都要相同吗。如果左边的分区数比右边大,子RDD的一个分区依赖父RDD多个分区的全部,应该也不需要shuffle吧。
2.groupByKey的默认分区器就是hashPartitoner吗,可以换吗
-
对于
rdd2 = rdd1.groupByKey(partitioner1)
,当partitioner1 == rdd1采用的partitioner
,也就是你说的分区器的类型和分区都要相同
时,groupByKey()不进行shuffle,而只进行mapPartitions()操作,详见combineByKeyWithClassTag
代码。除此以外,groupByKey()将进行shuffle。“如果左边的分区数比右边大,子RDD的一个分区依赖父RDD多个分区的全部“,这种情况属于NarrowDependency(见图3.2)不进行shuffle,不过这种情况目前只会出现在用户自定义的算子中,Spark代码中的groupByKey()算子没有对这种情况进行特殊检查和处理,因为进行检查的代价太高(检查保证相同key的records会被放到同一个partition中),所以目前groupByKey()的逻辑就是partitioner相同不进行shuffle,除此以外都进行shuffle。
-
可以换,比如下面代码将HashPartitioner换为RangePartitioner,不管什么partitioner,只要能将相同key的records放在同一分区即可。
package basic.transfromation
import org.apache.spark.sql.SparkSession
import org.apache.spark.{HashPartitioner, RangePartitioner}
object GroupByKeyExample {
def main(args: Array[String]): Unit = {
val spark = SparkSession
.builder
.appName("group by key example")
.master("local[1]")
.getOrCreate()
val sc = spark.sparkContext
val inputRDD = sc.parallelize(Array[(Int,Char)](
(2,'b'),(3,'c'),(1,'a'),(4,'d'),(5,'e'),(3,'f'),(2,'b'),(1,'h'),(2,'i')
),3)
val inputRDD2 = inputRDD.partitionBy(new HashPartitioner(3))
println("------------input rdd----------")
inputRDD2.mapPartitionsWithIndex((pid, iter)=>{
iter.map( value => "PID: " + pid + ", value: " + value)
}).foreach(println)
//val resultRDD = inputRDD2.groupByKey(3)
val resultRDD = inputRDD2.groupByKey(new RangePartitioner(3, inputRDD2))
println(resultRDD.toDebugString)
println("------------result rdd----------")
resultRDD.mapPartitionsWithIndex((pid, iter)=>{
iter.map( value => "PID: " + pid + ", value: " + value)
}).foreach(println)
System.in.read()
}
}