Spark SQL的Scala API - TimestampType - 找不到org.apache.spark.sql.types.TimestampType

时间:2017-06-01 20:57:49

标签: scala apache-spark timestamp apache-spark-sql apache-spark-dataset

我在Databricks笔记本上使用Spark 2.1和Scala 2.11

什么是TimestampType?

我们从SparkSQL's documentation知道官方时间戳类型是TimestampType,它显然是java.sql.Timestamp的别名:

TimestampType可以在SparkSQL的Scala API

中找到

使用架构和数据集API

时,我们有所不同

解析{"time":1469501297,"action":"Open"} from the Databricks' Scala Structured Streaming example

使用Json架构 - >好的(我更喜欢使用优雅的数据集API):

val jsonSchema = new StructType().add("time", TimestampType).add("action", StringType)

val staticInputDF = 
  spark
    .read
    .schema(jsonSchema)
    .json(inputPath)

使用数据集API - > KO :找不到TimestampType的编码器

创建Event类

import org.apache.spark.sql.types._
case class Event(action: String, time: TimestampType)
--> defined class Event

在databricks上从DBFS读取事件时出错。

注意:使用java.sql.Timestamp作为“时间”的类型时,我们不会收到错误

val path = "/databricks-datasets/structured-streaming/events/"
val events = spark.read.json(path).as[Event]

错误消息

java.lang.UnsupportedOperationException: No Encoder found for org.apache.spark.sql.types.TimestampType
- field (class: "org.apache.spark.sql.types.TimestampType", name: "time")
- root class: 

2 个答案:

答案 0 :(得分:7)

组合架构读取方法.schema(jsonSchema)和包含类型as[Type]的{​​{1}}方法将解决此问题。在阅读结构化流媒体文档Creating streaming DataFrames and streaming Datasets

后,我们想到了这个想法。
  

这些示例生成无类型的流式数据框架,这意味着   仅在编译时不检查DataFrame的架构   在提交查询时在运行时检查。有些操作如   map,flatMap等需要在编译时知道类型。去做   那些,你可以将这些无类型的流式数据帧转换为键入的   使用与静态DataFrame相同的方法传输数据集。

java.sql.Timestamp

将输出:

val path = "/databricks-datasets/structured-streaming/events/"

val jsonSchema = new StructType().add("time", TimestampType).add("action", StringType)

case class Event(action: String, time: java.sql.Timestamp)

val staticInputDS = 
  spark
    .read
    .schema(jsonSchema)
    .json(path)
    .as[Event]

staticInputDF.printSchema

答案 1 :(得分:3)

TimestampType不是java.sql.Timestamp的别名,而是Spark内部使用的时间戳类型的表示。通常,您不希望在代码中使用TimestampType。我们的想法是本地支持Spark java.sql.Timestamp,因此您可以按如下方式定义事件类:

case class Event(action: String, time: java.sql.Timestamp)

在内部,Spark会在编译和优化查询时使用TimestampType在运行时对值的类型进行建模,但这不是大多数时候您感兴趣的内容。