从火花源代码:
/**
* Represents the content of the Dataset as an `RDD` of `T`.
*
* @group basic
* @since 1.6.0
*/
lazy val rdd: RDD[T] = {
val objectType = exprEnc.deserializer.dataType
rddQueryExecution.toRdd.mapPartitions { rows =>
rows.map(_.get(0, objectType).asInstanceOf[T])
}
}
只要该mapPartitions
可以作为计算摆在首位的RDD
的时间。所以,这使得诸如操作
df.rdd.getNumPartitions
非常贵。鉴于一个DataFrame
是DataSet[Row]
和DataSet
由RDD
的。这就是为什么需要重新映射?任何见解表示赞赏。
TL; DR这是因为内部RDD
不RDD[Row]
。
考虑到一个数据帧是
DataSet[Row]
和DataSet
由RDD年代
这是一个巨大的过于简单化。首先,DataSet[T]
并不意味着你T
的容器进行交互。这意味着,如果你使用集合类API(通常被称为强类型),内部表示将被解码成T
。
内部表示是由Tungsten.This表示内部使用二进制格式是内部和变化和太低的水平受试者在实践中使用。
中间表示,它公开这个数据是InternalRow
- rddQueryExecution.toRDD
实际上RDD[InternalRow]
。这表示(有不同的实现),还是暴露了内部的类型,是考虑“弱”私人,如o.a.s.sql.catalyst
所有对象(访问未明确限制,但API未记录),以及相当棘手进行交互。
这其中,解码发挥作用,以及为什么需要完整的“重映射” - 要转换内部,往往是不安全的,对象为外部类型供公众使用。
最后,to reiterate我前面的说法 - 当getNumPartitions
被称为有问题的代码不会被执行。