Spark源码解析排序算子sortBy和sortByKey存在未排序的情况

一.在使用中出现的问题

 1 package test
 2 
 3 import org.apache.log4j.{Level, Logger}
 4 import org.apache.spark.sql.SparkSession
 5 
 6 /**
 7   * Created by Administrator on 2019/12/17.
 8   */
 9 object TestZip {
10   /**
11     * 设置日志级别
12     */
13   Logger.getLogger("org").setLevel(Level.WARN)
14   def main(args: Array[String]) {
15     val spark = SparkSession.builder().master("local[2]").appName(s"${this.getClass.getSimpleName}").getOrCreate()
16     val sc = spark.sparkContext
17     val array_left = 1 until 4 //生成1到count的数组
18     val array_right = Array("工单", "电力", "展示")
19 
20     val result = array_left.zip(array_right)
21     val rdd = sc.parallelize(result).sortBy(_._1)
22     val rdd2 = sc.parallelize(result).sortByKey(true)
23 
24     rdd.foreach(println)
25     println("----------------")
26     rdd2.foreach(println)
27   }
28 }

二.执行结果

![]()

从结果中可以看出,sortBy和sortByKey都没有实现排序的功能【虽然它们顺序已经改变】。这是怎么回事?

![]()

具体原因下面我们从源码中进行分析!

三.源码分析

![]()

在Spark的源码中,从RDD.scala代码中可以看出,sortBy底层调用的是sortByKey算子,在无升序降序的参数下【ascending】,默认为升序【true】,因此,我们只需要前往sortByKey中分析为什么没有实现排序功能即可。

![]()

1.在OrderedRDDFunctions.scala中,可以看见sortByKey实现的具体细节,从注释中可以看出,排序基于key,在每个分区内部实现一个排序序列,注意,是每个分区内,下面我们去重置分区为1来检验一下是否有效!

2.另外,注释也提到调用collect或者save也可以获取一个有序的序列,下面也一块去验证!

四.设置分区为1

![]()

执行结果:

![]()

由此可见,当设置分区数为1时【即合并所有分区为一个分区,显然之前的分区数不为1,查看存在多少分区数可以参考我的博客:<https://www.cnblogs.com/yszd/p/10156231.html&gt;】,可以实现升序排序,当然降序也是可以的

![]()

![]()

五.以collect为例进行验证

![]()

![]()

备注:由此可见,调用collect也可以实现排序,但调用collect之后会返回一个Array,不再是RDD!

六.原因分析

不管是repartition还是collect,其本质都是把各个executor中的数据汇总到master主节点中,是调用action算子,会存在repartition和shuffle操作。源码就很好的验证了这一点:

![]()

在sortByKey中,会调用分区算子进行重新分区,与显式调用repartition有异曲同工之妙!

![]()

而其中的ShuffledRDD会在shuffle执行过程中现在每个分区内进行排序,之后再进行整体的排序,以便提升排序性能,类似与归并排序算法!

声明:该文章系转载,转载该文章的目的在于更广泛的传递信息,并不代表本网站赞同其观点,文章内容仅供参考。

本站是一个个人学习和交流平台,网站上部分文章为网站管理员和网友从相关媒体转载而来,并不用于任何商业目的,内容为作者个人观点, 并不代表本网站赞同其观点和对其真实性负责。

我们已经尽可能的对作者和来源进行了通告,但是可能由于能力有限或疏忽,导致作者和来源有误,亦可能您并不期望您的作品在我们的网站上发布。我们为这些问题向您致歉,如果您在我站上发现此类问题,请及时联系我们,我们将根据您的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。