Spark RDD的take(1)和first()之间的区别

时间:2016-05-28 04:00:09

标签: apache-spark pyspark rdd

我曾经认为rdd.take(1)rdd.first()完全相同。然而,在我的同事向我指出Spark's officiation documentation on RDD后,我开始怀疑这是否真的如此:

  

first():返回此RDD中的第一个元素。

     

take(num):获取RDD的前几个数字元素。   它首先扫描一个分区,然后使用该分区的结果来估计满足限制所需的额外分区数。

我的问题是:

  1. first()的基础实施是否与take(1)相同?
  2. 假设rdd1rdd2是由同一个csv构建的,我可以放心地假设rdd1.take(1)rdd2.first()始终返回相同的内容结果,即csv的第一行?如果rdd1rdd2的分区方式不同,该怎么办?

3 个答案:

答案 0 :(得分:14)

Infact first是根据take实现的。

以下内容来自火花的RDD.scala来源。 first调用take(1)并返回第一个元素(如果找到)。

  def first(): T = withScope {
    take(1) match {
      case Array(t) => t
      case _ => throw new UnsupportedOperationException("empty collection")
    }
  }

take(num)尝试从RDD的第0个分区开始获取num个元素(如果考虑基于0的索引)。所以take(1)和first的行为是相同的。

即使是spark programming guide也证实了这一点。

关于你的第二个问题:当你说区别不同时,这取决于你的意思。如果您使用或不使用numPartitions调用sc.textFile("/path/to/file"),则无关紧要,因为第0个分区将始终为第0个分区。是的,你可以假设他们将拥有相同的第一个元素。

编辑:RDD中的分区是有序的,CSV中的物理第一行将在RDD的第0个分区中结束。并且take(1)first都将返回第0个分区的第一行。

答案 1 :(得分:5)

两者都不相同。

rdd.first()将返回此RDD中的第一个元素 而rdd.take(1)将返回一个只有第一个元素的数组。

  1. first()的底层实现与take(1)相同吗?
  2. Ans:在实现方面,first()在内部调用take(1)并返回第一个且只返回take(1)返回的数组元素。取自org.apache.spark.rdd.RDD类

      /**
       * Return the first element in this RDD.
       */
      def first(): T = withScope {
        take(1) match {
          case Array(t) => t
          case _ => throw new UnsupportedOperationException("empty collection")
        }
      }
    
    1. 假设rdd1和rdd2是从同一个csv构造的,我可以安全地假设rdd1.take(1)和rdd2.first()将始终返回相同的结果,即csv的第一行吗?如果rdd1和rdd2的分区方式不同怎么办?
    2. 答案:是的,您可以认为,分区不会改变读取输入的顺序。

答案 2 :(得分:0)

因此,似乎两者是相同的,但我们确实存在差异。

1。当我们从文件中读取数据时,默认情况下它是RDD,并且RDD具有first()take()属性。
2. first()属性返回行类型对象,而take()属性返回列表类型。

但是 使用.toDF()将RDD转换为DataFrame后,该DF上就没有first()属性。

希望它可以进一步澄清这些概念。

See the image for more clearity