[英]How to sort an RDD in Scala Spark?
读取Spark方法sortByKey:
sortByKey([ascending], [numTasks]) When called on a dataset of (K, V) pairs where K implements Ordered, returns a dataset of (K, V) pairs sorted by keys in ascending or descending order, as specified in the boolean ascending argument.
是否有可能仅返回“ N”个结果。 因此,除了返回所有结果之外,仅返回前10个即可。我可以将排序后的集合转换为Array并使用take
方法,但是由于这是O(N)操作,有没有更有效的方法?
如果只需要前十名,请使用rdd.top(10)
。 它避免了排序,因此速度更快。
rdd.top
使数据并行通过,收集堆中每个分区的前N个,然后合并堆。 这是一个O(rdd.count)操作。 排序将为O(rdd.count log rdd.count) ,并且会导致大量数据传输-它会进行随机排序,因此所有数据都将通过网络传输。
您很可能已经仔细阅读了源代码:
class OrderedRDDFunctions {
// <snip>
def sortByKey(ascending: Boolean = true, numPartitions: Int = self.partitions.size): RDD[P] = {
val part = new RangePartitioner(numPartitions, self, ascending)
val shuffled = new ShuffledRDD[K, V, P](self, part)
shuffled.mapPartitions(iter => {
val buf = iter.toArray
if (ascending) {
buf.sortWith((x, y) => x._1 < y._1).iterator
} else {
buf.sortWith((x, y) => x._1 > y._1).iterator
}
}, preservesPartitioning = true)
}
而且,正如您所说, 整个数据必须经过洗牌阶段-如摘要所示。
但是,您对随后调用take(K)的担心可能不太准确。 此操作不会循环浏览所有N个项目:
/**
* Take the first num elements of the RDD. It works by first scanning one partition, and use the
* results from that partition to estimate the number of additional partitions needed to satisfy
* the limit.
*/
def take(num: Int): Array[T] = {
这样看来:
O(myRdd.take(K))<< O(myRdd.sortByKey())〜= O(myRdd.sortByKey.take(k))(至少对于小K)<< O(myRdd.sortByKey()。collect ()
至少从PySpark 1.2.0起,另一个选择是使用takeOrdered 。
升序排列:
rdd.takeOrdered(10)
降序排列:
rdd.takeOrdered(10, lambda x: -x)
k,v对的前k个值:
rdd.takeOrdered(10, lambda (k, v): -v)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.