簡體   English   中英

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

[英]Spark SQL's Scala API - TimestampType - No Encoder found for org.apache.spark.sql.types.TimestampType

我在Databricks筆記本上使用Spark 2.1和Scala 2.11

什么是TimestampType?

我們知道,從SparkSQL的文檔那是官方的時間戳類型是TimestampType,這顯然是對的java.sql.Timestamp一個別名:

TimestampType可以在SparkSQL的Scala API中找到

使用模式和數據集API時,我們有所不同

解析Databricks的Scala Structured Streaming示例中的 {"time":1469501297,"action":"Open"}

使用Json架構 - > OK (我更喜歡使用優雅的Dataset 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作為“time”的類型時,我們不會收到錯誤

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: 

結合模式讀取方法.schema(jsonSchema)和包含類型java.sql.Timestampas[Type]方法將解決此問題。 這個想法是在閱讀Structured Streaming文檔創建流式數據框架和流式數據集之后得出的

這些示例生成無類型的流式DataFrame,這意味着在編譯時不檢查DataFrame的架構,僅在提交查詢時在運行時檢查。 map,flatMap等一些操作需要在編譯時知道類型。 要執行這些操作, 您可以使用與靜態DataFrame相同的方法將這些無類型流式DataFrame轉換為類型化流式數據集。

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

將輸出:

root
 |-- time: timestamp (nullable = true)
 |-- action: string (nullable = true)

TimestampType不是java.sql.Timestamp的別名,而是Spark內部使用的時間戳類型的表示。 通常,您不希望在代碼中使用TimestampType 我們的想法是本地支持Spark SQL的java.sql.Timestamp ,因此您可以按如下方式定義事件類:

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

在內部,Spark將在編譯和優化查詢時使用TimestampType在運行時對值的類型進行建模,但這不是您在大多數時間感興趣的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM