【Spark】Saving data in the Hive serde table is not supported yet

问题描述

最近收到一个任务报错:

Saving data in the Hive serde table bigdata.books is not supported yet. Please use the insertInto() API as an alternative..;

简单描述下业务逻辑:

  1. 判断要操作的表是否存在,如果存在drop掉该表:

spark.sql("use bigdata")
spark.sql("DROP TABLE IF EXISTS books")

  1. 创建表:

spark.sql("create table books(a int,b string)")

  1. 构造dataframe:

val df = spark.sql("...业务数据...")

  1. 数据写入表:

df.write.mode(SaveMode.Append).saveAsTable("books")

问题分析

第2步其实是创建了一个hive表,创建的这个表books在hive层面是兼容的,即通过spark写入到books的数据通过hiveSQL是可以读的,那还有hive不能读的情况吗?答案是:有!

Spark内部其实是有两套API的:DataSource API和 基于Hive实现的API。在创建表的时候,如果不显示使用例如using parquet 指定source的话,默认是创建hive兼容表的,就像上面第2步代码一样。如果指定了source,比如:

spark.sql("create table using parquet books(a int,b string)")
那么books表中的数据,使用hiveSQL就不一定能读到。

DataSource API创建的表的meta信息写入了Hive metaStore,但是hiveSQL并不能辨认,导致数据是读不出来的。

回到上面的报错。因为第2步创建了一张hive兼容表,但是saveAsTable其实是DataSource API,即使用DataSource API像Hive兼容表里保存数据,Spark现在的版本(spark-2.1.0)还是不支持的。

怎么知道saveAsTable是DataSourceAPI 呢,就需要跟一下代码了:
找到DataFrame写入口DataFrameWritesaveAsTable方法,跟到最后:

【Spark】Saving data in the Hive serde table is not supported yet_第1张图片
saveAsTable.png

找到执行的逻辑计划,进入 CreateTable看一下:

【Spark】Saving data in the Hive serde table is not supported yet_第2张图片
CreateTable.png

它对应的是datasource 级别的ddl,这样就很清楚了。
关于DataSource 的源码分析,后面会专门写一篇文章分析一下。

问题解决

那怎么解决上面的问题呢?
思路就是保持API的一致。就上面具体问题来说,有两种方案:

  1. 错误里面提示了,使用insertInto("table")替代:insertInto 就是Hive兼容的API,用它写入的数据通过hiveSQL是能够读出来的。
  2. 不事先创建table表,直接通过saveAsTable创建,创建出的表跟df有同样的schema。但是注意,这样创建的表就是DataSource表了,通过hiveSQL可能是读不了的。

所以如果需要hiveSQL能读,就要选择第1种解决方案。

你可能感兴趣的:(【Spark】Saving data in the Hive serde table is not supported yet)