任何人都可以解释一下, RDD转换的结果是什么?它是新的数据集(数据副本)还是只是新的指针集,用于过滤旧数据块?
答案 0 :(得分:13)
RDD转换允许您在RDD之间创建依赖关系。依赖关系只是产生结果的步骤(程序)。沿袭链中的每个RDD(依赖性串)具有用于计算其数据的函数,并且具有指向其父RDD的指针(依赖性)。 Spark会将RDD依赖项划分为阶段和任务,并将这些依赖项发送给工作人员执行。
所以,如果你这样做:
val lines = sc.textFile("...")
val words = lines.flatMap(line => line.split(" "))
val localwords = words.collect()
单词将是包含对行RDD的引用的RDD。当程序执行时,第一行'将执行函数(从文本文件加载数据),然后单词'将对结果数据执行函数(将分割行分割为单词)。 Spark很懒,所以除非你调用一些会触发作业创建和执行的转换或动作(在这个例子中收集),否则什么都不会执行。
因此,RDD(转换后的RDD)也不是一组数据,而是程序中的一步(可能是唯一的一步)告诉Spark如何获取数据以及如何获取数据做它。
答案 1 :(得分:3)
转换基于现有RDD创建新RDD。基本上,RDD是不可变的。 Spark中的所有转换都是lazy.RDD中的数据在执行acton之前不会被处理。
RDD转换示例: 地图,过滤器,flatMap,groupByKey,reduceByKey
答案 2 :(得分:2)
正如其他人所提到的,RDD维护了一个以编程方式应用于它的所有转换的列表。这些是懒惰的评估,所以虽然(例如在REPL中),你可能得到一个不同参数类型的结果(例如,在应用地图之后),'new'RDD还没有包含任何东西,因为没有任何东西强迫原始RDD评估其血统中的变换/过滤器。诸如count
之类的方法,各种约简方法等将导致应用传输。 checkpoint
方法也应用所有RDD操作,返回RDD,这是传输的结果但没有沿袭(这可能是性能优势,尤其是对于迭代应用程序)。
答案 3 :(得分:1)
所有答案都完全有效。我只想添加一张快速图片:-)
答案 4 :(得分:0)
转换是一种将RDD数据从一种形式转换为另一种形式的操作。当你在任何RDD上应用这个操作时,你将获得一个带有转换数据的新RDD(Spark中的RDD是不可变的,记住????)。 地图,过滤器, flatMap 等操作是转换。
现在需要注意的是,当您在任何RDD上应用转换时,它将不会立即执行操作。它将使用应用的操作,源RDD和用于转换的函数创建 DAG (有向无环图)。并且它将继续使用引用构建此图形,直到您在最后排列的 RDD 上应用任何操作操作。这就是为什么Spark中的转换是懒惰的。
答案 5 :(得分:0)
其他答案已经给出了很好的解释。这是我的一些美分:
要清楚地了解返回RDD的内部内容,最好检查一下RDD抽象类(从源代码引用)里面的内容:
内部,每个RDD具有五个主要属性:
- 分区列表
- 用于计算每个细分的功能
- 对其他RDD的依赖关系列表
- (可选)键值RDD的分区程序(例如,该RDD是哈希分区的)
- (可选)用于计算每个细分的首选位置列表(例如,HDFS文件的块位置)