簡體   English   中英

如何在Scala Spark中對RDD進行排序?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM