据我所知,有两种类型的依赖关系: narrow&宽即可。但我不明白依赖会如何影响子RDD 。 子RDD 仅包含有关如何从父RDD 构建新RDD块的信息的元数据?或者子RDD 是从父RDD 创建的自给自足数据集?
答案 0 :(得分:8)
是的,子RDD是描述如何从父RDD计算RDD的元数据。
例如考虑org/apache/spark/rdd/MappedRDD.scala
:
private[spark]
class MappedRDD[U: ClassTag, T: ClassTag](prev: RDD[T], f: T => U)
extends RDD[U](prev) {
override def getPartitions: Array[Partition] = firstParent[T].partitions
override def compute(split: Partition, context: TaskContext) =
firstParent[T].iterator(split, context).map(f)
}
当您说rdd2 = rdd1.map(...)
时,rdd2
将是MappedRDD
。 compute
仅在稍后执行,例如当您致电rdd2.collect
时。
RDD始终是这样的元数据,即使它没有父节点(例如sc.textFile(...)
)。 RDD存储在节点上的唯一情况是,如果您使用rdd.cache
将其标记为缓存,则会导致计算它。
另一种类似的情况是调用rdd.checkpoint
。此功能标记RDD以进行检查点。下次计算时,它将被写入磁盘,稍后访问RDD将导致从磁盘读取而不是重新计算。
cache
和checkpoint
之间的区别在于缓存的RDD仍然保留其依赖关系。缓存的数据可以在内存压力下丢弃,并且可能需要部分或全部重新计算。检查点RDD不会发生这种情况,因此依赖关系会被丢弃。