火花数据框密封特征类型
Posted
技术标签:
【中文标题】火花数据框密封特征类型【英文标题】:spark dataframe to sealed trait type 【发布时间】:2018-06-19 10:48:06 【问题描述】:我有一些数据存储为 parquet 文件和与数据模式匹配的案例类。 Spark 可以很好地处理常规产品类型,所以如果我有
case class A(s:String, i:Int)
我可以轻松做到
spark.read.parquet(file).as[A]
但据我了解,Spark 不处理析取类型,所以当我在镶木地板中有枚举时,以前编码为整数,以及像这样的 scala 表示
sealed trait E
case object A extends E
case object B extends E
我做不到
spark.read.parquet(file).as[E]
// java.lang.UnsupportedOperationException: No Encoder found for E
到目前为止是有道理的,但是,可能太天真了,我尝试了
implicit val eEncoder = new org.apache.spark.sql.Encoder[E]
def clsTag = ClassTag(classOf[E])
def schema = StructType(StructField("e", IntegerType, nullable = false)::Nil)
我仍然得到相同的“找不到 E 编码器”:(
此时我的问题是,为什么范围内的隐含缺失? (或不被识别为编码器[E]),即使是这样,这样的接口如何允许我实际解码数据?我仍然需要将值映射到正确的案例对象。
我确实读过a related answer,上面写着“TL;DR 目前没有好的解决方案,鉴于 Spark SQL / Dataset 的实施,在可预见的将来不太可能有这样的解决方案。”但我很难理解为什么自定义编码器无法做到这一点。
【问题讨论】:
【参考方案1】:但我很难理解为什么自定义编码器无法做到这一点。
两个主要原因:
没有自定义 Encoders
的 API。公开可用的只有“二进制”Kryo 和 Java Encoders
,它们会创建无用的(在 DataFrame
/ Dataset[Row]
的情况下)不支持任何有意义的 SQL / DataFrame
操作的 blob。
这样的代码可以正常工作
import org.apache.spark.sql.Encoders
spark.createDataset(Seq(A, B): Seq[E])(Encoders.kryo[E])
但这只不过是一种好奇心。
DataFrame
是一个列商店。在此结构之上编码类型层次结构在技术上是可能的(私有 UserDefinedType
API 会这样做),但它很麻烦(因为您必须为所有可能的变体提供存储,例如参见 How to define schema for custom type in Spark SQL?)并且效率低下(通常在 Spark SQL 中,复杂类型在某种程度上是二等公民,许多优化无法通过复杂模式访问,未来可能会发生变化)。
从更广泛的意义上讲,DataFrame
API 是有效的关系型(如在 relational algebra 中),元组(关系的主要构建块)在定义上是同质的,因此通过扩展,SQL / DataFrame
API 中没有位置,因为异构结构。
【讨论】:
感谢您的回答。真正手头的案例是包含枚举作为其某些字段的案例类。其中 enum 只不过是一个 int 上的名称,所以在简单的情况下,我们不处理异构类型,这个限制非常令人沮丧,因为我们所有的案例类都不可用(不是你的错):)以上是关于火花数据框密封特征类型的主要内容,如果未能解决你的问题,请参考以下文章