我对PySpark有点陌生(更多是对Spark-Scala的了解),最近我遇到了下面的观察。当我使用parallelize()方法创建RDD时,返回类型为 RDD 类型。但是,当我使用range()方法创建RDD时,其类型为 PipelinedRDD 。例如:
>>> listRDD =sc.parallelize([1,2,3,4,5,6,7])
>>> print(listRDD.collect())
[1, 2, 3, 4, 5, 6, 7]
>>> print(type(listRDD))
<class 'pyspark.rdd.RDD'>
>>> rangeRDD =sc.range(1,8)
>>> print(rangeRDD.collect())
[1, 2, 3, 4, 5, 6, 7]
>>> print(type(rangeRDD))
<class 'pyspark.rdd.PipelinedRDD'>
我检查了两个rdds的构造和发现方式:
1)内部都只使用parallize方法。
>>> rangeRDD.toDebugString()
b'(8) PythonRDD[25] at collect at <stdin>:1 []\n | ParallelCollectionRDD[24] at parallelize at PythonRDD.scala:195 []'
>>> listRDD.toDebugString()
b'(8) PythonRDD[26] at RDD at PythonRDD.scala:53 []\n | ParallelCollectionRDD[21] at parallelize at PythonRDD.scala:195 []'
2)PipeLineRDD是我理解的RDD类的子类。
但是,当它的类型为PipeLineedRDD以及它的类型为RDD时,是否有任何通用逻辑? 谢谢大家。
答案 0 :(得分:1)
sc.range
实际上是在内部调用parallelize
方法-它是here定义的。您可以看到sc.range
正在使用xrange作为输入来调用sc.parallelize
。并且sc.parallelize
在使用xrange输入类型进行调用时有一个单独的代码分支:它以空列表作为参数调用自身,然后应用mapPartitionsWithIndex
here,这是{{1}的最终输出}和sc.parallelize
依次呼叫。因此,您可以看到如何像使用sc.range
一样创建第一个常规对象(尽管对象是一个空列表),但是最终输出是在其之上应用映射功能的结果。
看来,此行为的主要原因是避免具体化否则会发生的数据(如果未实现len,则将对其进行迭代并立即转换为列表)。