为什么星火据帧转换为RDD需要完全重新映射?

问题描述 投票:9回答:1

从火花源代码:

/**
   * 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])
    }
  }

https://github.com/apache/spark/blob/master/sql/core/src/main/scala/org/apache/spark/sql/Dataset.scala#L2972

只要该mapPartitions可以作为计算摆在首位的RDD的时间。所以,这使得诸如操作

df.rdd.getNumPartitions

非常贵。鉴于一个DataFrameDataSet[Row]DataSetRDD的。这就是为什么需要重新映射?任何见解表示赞赏。

scala apache-spark
1个回答
7
投票

TL; DR这是因为内部RDDRDD[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被称为有问题的代码不会被执行。

© www.soinside.com 2019 - 2024. All rights reserved.