Apache spark Dataset.rdd是操作还是转换?
评估数据帧是否为空的方法之一是执行Apache spark Dataset.rdd是操作还是转换?,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,评估数据帧是否为空的方法之一是执行df.rdd.isEmpty(),但是,我在sparkUI执行中看到mycode.scala:123处的rdd。这让我想知道这个rdd()函数是否实际上是一个动作,而不是一个转换 我知道isEmpty()是一个动作,但我确实看到mycode.scala:234的isEmpty()有一个单独的阶段,所以我认为它们是不同的动作?rdd是用“rdd术语”来表示结构化查询的,所以Spark可以执行它。它是您的类型T的JVM对象的RDD。如果使用不当,可能会导致内存问题,
df.rdd.isEmpty()
,但是,我在sparkUI执行中看到mycode.scala:123处的rdd。这让我想知道这个rdd()函数是否实际上是一个动作,而不是一个转换
我知道isEmpty()是一个动作,但我确实看到mycode.scala:234的isEmpty()有一个单独的阶段,所以我认为它们是不同的动作?rdd
是用“rdd术语”来表示结构化查询的,所以Spark可以执行它。它是您的类型T
的JVM对象的RDD。如果使用不当,可能会导致内存问题,因为:
将位于JVM外部的内部管理的优化行传输到JVM中的内存空间
将二进制行转换为业务对象(JVM“true”表示)
前者将增加计算所需的JVM内存,而后者是一个额外的转换步骤
对于这样一个计算行数的简单计算,您宁愿坚持使用count
作为优化且相当便宜的计算(这可以避免复制对象和应用模式)
在内部,Dataset
将行保留在其InternalRow
中。这降低了Spark应用程序的JVM内存需求。计算RDD(来自RDD
)以表示火花动作执行后将执行的火花变换
请注意,执行rdd
会创建一个rdd,并且也需要一些计算
因此,是的,rdd
在“执行”查询时可能被视为一个操作(即位于后面的数据集的物理计划),但最终它只给出了一个rdd
(因此,根据定义,它不能是一个操作,因为Spark actions返回一个非rdd值)
如图所示:
比较下面的RDD谱系,并思考哪一个看起来更好
val dataset = spark.range(5).withColumn("group", 'id % 2)
scala> dataset.rdd.toDebugString
res1: String =
(8) MapPartitionsRDD[8] at rdd at <console>:26 [] // <-- extra deserialization step
| MapPartitionsRDD[7] at rdd at <console>:26 []
| MapPartitionsRDD[6] at rdd at <console>:26 []
| MapPartitionsRDD[5] at rdd at <console>:26 []
| ParallelCollectionRDD[4] at rdd at <console>:26 []
// Compare with a more memory-optimized alternative
// Avoids copies and has no schema
scala> dataset.queryExecution.toRdd.toDebugString
res2: String =
(8) MapPartitionsRDD[11] at toRdd at <console>:26 []
| MapPartitionsRDD[10] at toRdd at <console>:26 []
| ParallelCollectionRDD[9] at toRdd at <console>:26 []
正如您在(上面粘贴的)中所看到的,最后请求rdd
将触发一个额外的计算来获取rdd
创建一个新的逻辑计划来反序列化数据集的逻辑计划,即从JVM外部管理的内部二进制行格式中获得额外的反序列化,以其对应的表示形式表示为JVM内的JVM对象(想想你应该不惜一切代价避免的GC)
谢谢你的解释,我还有一个问题,count()也是一个动作,必须计算所有行。虽然rdd.isEmpty()只执行take(1),所以在这种情况下可能会更快,对吗?@linehrr添加了关于rdd的新部分。如果你还需要什么,请告诉我。让我们消除所有的疑虑!快乐火花!:)
df.queryExecution.toRdd.isEmpty
val dataset = spark.range(5).withColumn("group", 'id % 2)
scala> dataset.rdd.toDebugString
res1: String =
(8) MapPartitionsRDD[8] at rdd at <console>:26 [] // <-- extra deserialization step
| MapPartitionsRDD[7] at rdd at <console>:26 []
| MapPartitionsRDD[6] at rdd at <console>:26 []
| MapPartitionsRDD[5] at rdd at <console>:26 []
| ParallelCollectionRDD[4] at rdd at <console>:26 []
// Compare with a more memory-optimized alternative
// Avoids copies and has no schema
scala> dataset.queryExecution.toRdd.toDebugString
res2: String =
(8) MapPartitionsRDD[11] at toRdd at <console>:26 []
| MapPartitionsRDD[10] at toRdd at <console>:26 []
| ParallelCollectionRDD[9] at toRdd at <console>:26 []
rdd: RDD[T]