07_spark_core_键值对RDD分区规则
键值对RDD数据分区
Spark目前支持Hash分区、Range分区和用户自定义分区。Hash分区为当前的默认分区。分区器直接决定了RDD中分区的个数、RDD中每条数据经过Shuffle后进入哪个分区和Reduce的个数。
1)注意:
(1)只有Key-Value类型的RDD才有分区器,非Key-Value类型的RDD分区的值是None
(2)每个RDD的分区ID范围:0~numPartitions-1,决定这个值是属于那个分区的。
2)获取RDD分区
(1)创建包名:com.atguigu.partitioner
(2)代码实现
package com.atguigu.partitioner
import com.atguigu.keyvalue.MyPartitioner
import org.apache.spark.rdd.RDD
import org.apache.spark.{HashPartitioner, SparkConf, SparkContext}
/**
* @author dxy
* @date 2021/2/25 12:47
*/
object partitioner01_get {
def main(args: Array[String]): Unit = {
//TODO 1.创建SparkConf并设置App名称
val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")
//TODO 2.创建SparkContext,该对象是提交Spark App的入口
val sc: SparkContext = new SparkContext(conf)
val strRDD: RDD[String] = sc.makeRDD(List("atguigu","zoo","hive","banana","spark","hadoop"))
println(strRDD.partitioner)
val mapRDD: RDD[(String, Int)] = strRDD.map((_,1))
println(mapRDD.partitioner)
val hashRDD: RDD[(String, Int)] = mapRDD.partitionBy(new HashPartitioner(2))
println(hashRDD.partitioner)
val myRDD: RDD[(String, Int)] = mapRDD.partitionBy(new MyPartitioner(2))
println(myRDD.partitioner)
//TODO 3.关闭连接
sc.stop()
}
}
运行结果:
None
None
Some(org.apache.spark.HashPartitioner@2)
Some(com.atguigu.keyvalue.MyPartitioner@2301b75)
自定义分区器
class MyPartitioner(num:Int) extends Partitioner{
override def numPartitions: Int = num
override def getPartition(key: Any): Int = {
if (key.isInstanceOf[Int]){
val keyInt: Int = key.asInstanceOf[Int]
if (keyInt<=2){
0
}else{
1
}
}else{
1
}
}
override def equals(other: Any): Boolean = other match {
case h: MyPartitioner =>
h.numPartitions == numPartitions
case _ =>
false
}
}
总结
Spark目前支持Hash分区、Range分区和用户自定义分区。Hash分区为当前的默认分区。分区器直接决定了RDD中分区的个数、RDD中每条数据经过Shuffle后进入哪个分区和Reduce的个数。
1)注意:
(1)只有Key-Value类型的RDD才有分区器,非Key-Value类型的RDD分区的值是None
(2)每个RDD的分区ID范围:0~numPartitions-1,决定这个值是属于那个分区的。
查看分区器
rdd.partitioner.sout