Spark先分区再排序

处理数据时,比我们想对一个年级的所有语文考试成绩先按班级分类,再在每个班级里按成绩排名,最终每个班级的数据保存为一个文件,这就要用到spark分区加排序的技巧

数据为DF格式时

代码

 val spark  =SparkSession.builder().config(new SparkConf()).getOrCreate()
       val sc =spark.sparkContext
       val data = sc.parallelize(Array((100,2),(200,1),(300,3),(100,4),(200,4),(300,8) ,(200,5),(300,6),(100,5),(100,0),(200,6),(200,-1)))

       import spark.implicits._
       val DF_sort_partition =data.toDF("key","value")
         .sort(desc("value"))
         .write
         .partitionBy("key")
         .mode(SaveMode.Overwrite)
         .parquet("develop/wangdaopeng/partitionTest")

       val s1 =spark.read.parquet("develop/wangdaopeng/partitionTest/key=100").show()
       val s2 =spark.read.parquet("develop/wangdaopeng/partitionTest/key=200").show()
结果的保存形式

在这里插入图片描述
因为我们是根据"key"字段来保存,所以保存结果的目录是key=xx的形式,每个key对应一个分区

结果内容

key=100:
在这里插入图片描述
key=200:
在这里插入图片描述
结果完全符合预期

数据为RDD格式时

如果像DF格式那样写,是达不到预期的效果的,比如下列代码
先排序再分区

          data
         .sortBy(_._2)
         .partitionBy(new HashPartitioner(3))

或者先分区再排序

			data
           .partitionBy(new HashPartitioner(3))
           .sortBy(_._2)

结果都是不符合预期的
对于RDD,一种简单的先分区再再分区里进行排序的方法如下,先repartition,RDD的partitionBy默认都是根据key值来进行的(对于pair 对,就是第一个元素),mapPartitions 输入和返回的都是一个迭代器,排序的方法在于先把iterator转化为list 排序再以iterator的形式返回


   val res =data
          .partitionBy(new HashPartitioner(3))
          .mapPartitions{x=>
              x.toList.sortBy(_._2).toIterator
          }
          .saveAsTextFile(path)

结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值