spark sortBy与 zipWithIndex原理

一、为什么要看源码了解其原理呢?(可忽略)

因为项目中需要做排行榜,也就是需要排序,且给出对应排名。

搜索了不少资料,模模糊糊的貌似通过sortBy+zipWithIndex两个算子就能做到。但是就是不敢用。

第一:

不知道sortBy是怎么做到全局排序的,是否有性能问题,导致不太敢用。因为之前学习hadoop的mapreduce,以及hive,了解到全局排序会把所有数据都shuffle到一个reduce里面进行排序(当然,有优化方案)

如果数据量很大,spark也是通过这种方式实现全局排序的话,那spark一个task所需要的内存那会非常大,并且最终只有一个task会需要这么大的内存,那肯定不行。所以由于不清楚spark全局排序的原理,就不敢用,或者想自己实现归并排序。

第二:

不知道zipWithIndex的功能,主要是这个api的文档说的不清楚。

如图,圈起来的部分,这个说第一个分区的第一项索引为0,最后一个分区的最后一项为最大的索引。但是否有序?怎么个有序?在zipWithIndex之前执行了sortBy之后,是否会重新shufflue导致打乱顺序?

然后在圈起来的注释下一段又说和scala集合的zipWithIndex是一样的,这就让我觉得这个算子应该是我想像中的那样,会保证顺序,然后按顺序给每个元素递增索引。。

但这不能靠猜测,要么就用大规模数据测试一下,要么就翻源码。

 

我选择了后者,看源码。

 

二、原理

1、sortBy 原理

其实就是使用了RangePartitioner分区器

该分区器的实现方式主要是通过两个步骤来实现的,

(1)、先重整个RDD中抽取出样本数据,将样本数据排序,计算出每个分区的最大key值,形成一个Array[KEY]类型的数组变量rangeBounds;

(2)、判断key在rangeBounds中所处的范围,给出该key值在下一个RDD中的分区id下标

 

这样在分区号大的分区数据就比分区号小的分区数据大了,然后在各个分区内部再分别进行排序,这样的话就全局有序了(按分区号从小到大遍历数据,输出结果就是全局从小到大了)

 

2、zipWithIndex原理

(1)、计算每个分区的数量,然后计算每个分区的第一个元素在全局数据中的位置(index)

(2)、重写getPartitions函数,封装分区数据

正常RDD使用Partition对象存储分区号等信息,而当前zipWithIndexRDD又使用ZippedWithIndexRDDPartition封装进每个分区的第一个元素在全局数据的位置index。

(3)、重写compute函数,RDD会根据分区数n,调用n次该函数。该函数的作用就是重新封装每个分区数据的迭代器。

      参数中,Partition对象又被传进来了,这个对象其实是上面getPartitions函数返回的n多个分区数据之一,也就是说,

这Partition对象其实是ZippedWithIndexRDDPartition类型的实例,所以可以强转类型,获取该分区的第一个元素在全局数据的位置index。

     然后调用getIteratorZipWithIndex函数封装新的迭代器(给每个元素配上该元素在全局数据中的位置),其实就是从该分区一个元素的index开始累加,代码逻辑不复杂。

 

 

 

 

 

 

 

 

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spark中的sort by和order by是用于对数据进行排序的操作。sort by是将数据放到多个reduce里面进行排序,排序后每一个reduce里面的数据是有序的,但是全部数据不一定有序。如果reduce个数为1,此时全部数据有序,等价于order by操作。当需要对全部数据排序时,可以先使用sort by局部排序(sort by可以设置reduce个数),然后再使用order by排序,将会大大提高效率。\[1\] Spark采用的排序方法是TIMSort,它是归并排序的优化版,并且在小数据量时切换为binarySort来提升效率。无论是TimSort还是binarySort都是排序稳定的,因此不应该出现多次结果不一致的情况。在Spark的代码中,可以追踪到ShuffleInMemorySorter类中的insertRecord方法,该方法用于将记录插入到排序器中。\[2\] 另外,Spark中还有其他与排序相关的操作,如group by、distribute by和order by。group by将相同的key放到同一个reduce中,但后面必须跟聚合操作;distribute by和group by的作用类似,都是将key值相同的数据放到同一个reduce中;而order by是全局排序,而sort by是局部排序,当sort by中reduce为1时,等价于order by。\[3\] #### 引用[.reference_title] - *1* *3* [【Hive】sort by、order by、 distribute by、 group by 、cluster by区别](https://blog.csdn.net/Asher117/article/details/108979573)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [避坑:Spark Sql的Order By排序是不稳定的](https://blog.csdn.net/weixin_39445556/article/details/121072103)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值