13

查看select()spark DataSet 上的函数,有各种生成的函数签名:

(c1: TypedColumn[MyClass, U1],c2: TypedColumn[MyClass, U2] ....)

这似乎暗示我应该能够直接引用 MyClass 的成员并且类型安全,但我不确定如何......

ds.select("member")当然有效..似乎ds.select(_.member)也可以以某种方式工作?

4

2 回答 2

20

在 Scala DSL for 中select,有很多方法可以识别Column

  • 从一个符号:'name
  • 从字符串:$"name"col(name)
  • 从一个表达式:expr("nvl(name, 'unknown') as renamed")

TypedColumn要从您那里获得,Column只需使用myCol.as[T].

例如:ds.select(col("name").as[String])

于 2016-07-28T17:07:05.983 回答
19

如果你想要相当于ds.select(_.member)只使用map

case class MyClass(member: MyMember, foo: A, bar: B)
val ds: DataSet[MyClass] = ???
val members: DataSet[MyMember] = ds.map(_.member)

编辑:不使用的论点map

一种更高效的方法是通过投影,根本不使用map。您失去了编译时类型检查,但作为交换,Catalyst 查询引擎有机会做一些更优化的事情。正如@Sim 在下面的评论中所暗示的那样,主要的优化中心围绕着不需要MyClass将整个内容从 Tungsten 内存空间反序列化到 JVM 堆内存中——只是为了调用访问器——然后将结果序列化_.member回 Tungsten。

举一个更具体的例子,让我们重新定义我们的数据模型,如下所示:

  // Make sure these are not nested classes 
  // (i.e. in a top level compilation units).
  case class MyMember(something: Double)
  case class MyClass(member: MyMember, foo: Int, bar: String)

这些需要是case类,以便可以为我们提供API所需SQLImplicits.newProductEncoder[T <: Product]的隐式。Encoder[MyClass]Dataset[T]

现在我们可以让上面的例子更具体:

  val ds: Dataset[MyClass] = Seq(MyClass(MyMember(1.0), 2, "three")).toDS()
  val membersMapped: Dataset[Double] = ds.map(_.member.something)

要查看幕后发生的事情,我们使用以下explain()方法:

membersMapped.explain()

== Physical Plan ==
*(1) SerializeFromObject [input[0, double, false] AS value#19]
+- *(1) MapElements <function1>, obj#18: double
   +- *(1) DeserializeToObject newInstance(class MyClass), obj#17: MyClass
      +- LocalTableScan [member#12, foo#13, bar#14]

这使得与 Tungsten 之间的序列化非常明显。

让我们使用投影[^1] 得到相同的值:

val ds2: Dataset[Double] = ds.select($"member.something".as[Double])
ds2.explain()

== Physical Plan ==
LocalTableScan [something#25]

就是这样!一步[^2]。除了编码MyClass到原始数据集之外,没有序列化。

[^1]:投影被定义为与 Catalyst 自动投影单列$"member.something"DataFrame$"value.member.something"的成员无关的原因。

[^2]:公平地说,第*一个物理计划中的步骤旁边表明它们将由以下WholeStageCodegenExec步骤实现给它。因此,在实践中,您必须凭经验测试性能,才能真正评估每种方法的好处。

于 2017-05-11T15:38:28.063 回答