从 Spark 写入 Hive 表,指定 CSV 作为格式
Posted
技术标签:
【中文标题】从 Spark 写入 Hive 表,指定 CSV 作为格式【英文标题】:Writing Hive table from Spark specifying CSV as the format 【发布时间】:2017-08-15 00:00:31 【问题描述】:我在从 Spark 写入 Hive 表时遇到问题。下面的代码工作得很好;我可以编写表格(默认为 Parquet 格式)并在 Hive 中读回:
df.write.mode('overwrite').saveAsTable("db.table")
hive> describe table;
OK
val string
Time taken: 0.021 seconds, Fetched: 1 row(s)
但是,如果我指定格式应该是 csv:
df.write.mode('overwrite').format('csv').saveAsTable("db.table")
然后我可以保存表,但 Hive 无法识别架构:
hive> describe table;
OK
col array<string> from deserializer
Time taken: 0.02 seconds, Fetched: 1 row(s)
另外值得注意的是,我可以手动创建一个Hive表,然后insertInto
它:
spark.sql("create table db.table(val string)")
df.select('val').write.mode("overwrite").insertInto("db.table")
这样做,Hive 似乎可以识别架构。但这很笨拙,而且我无论如何也想不出一种自动化模式字符串的方法。
【问题讨论】:
Dataframe 的架构是什么?数据中有逗号吗? df.printSchema的输出是什么? 为什么是“笨重”?您想要创建一个符合 Hive 的数据集,因此使用符合 Hive 的方法来创建它似乎是合理的。为了记录,Parquet 更糟糕,因为默认情况下 Spark 不使用与 Hive 相同的二进制编码......并且没有记录覆盖该默认值的方法 cf。 [SPARK-20937] @cricket_007 和 Ankush Singh:架构和数据很简单,我尝试过各种方法。即使是具有单个整数列的 DataFrame 也无法写入 Hive 可以读取的模式(使用 csv 格式)。 @samsonScharfrichter 我说“笨拙”是因为您必须编写一个符合 hive 的模式字符串。当使用默认格式的saveAsTable
时,您不必这样做。我没有遇到 Parquet 的二进制编码问题。感谢您的提醒!
【参考方案1】:
那是因为Hive SerDe
默认不支持csv
。
如果你坚持使用csv
格式,创建表格如下:
CREATE TABLE my_table(a string, b string, ...)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
"separatorChar" = "\t",
"quoteChar" = "'",
"escapeChar" = "\\"
)
STORED AS TEXTFILE;
并通过df.write.insertInto
插入数据
更多信息:
https://cwiki.apache.org/confluence/display/Hive/CSV+Serde
【讨论】:
感谢您的信息。我提到过这种策略有效,但它很笨拙,因为您必须生成模式字符串 (a string, b string, ...
)。这是 Spark 编写一个 Spark 和 Hive 都可以读取的表的唯一解决方案吗?【参考方案2】:
您正在创建一个文本格式的表格并尝试将 CSV 数据插入其中,这可能会遇到问题。因此,正如张彤在回答中所建议的那样,使用 hive OpenCSVSerde 创建 hive 表。
之后,如果你对 Hive 查询语言比对数据框更熟悉,你可以试试这个。
df.registerTempTable("temp")
spark.sql("insert overwrite db.table select * from temp")
【讨论】:
我不确定我是否完全遵循。saveAsTable
的默认值是 Parquet,它工作得很好。当然,Hive SerDe 本身也不支持 Parquet。对吗?
很抱歉给您带来了困惑。我的实际意思是,使用所需的任何格式创建配置单元表。然后只需将数据框中的数据写入配置单元表。这样,你在写的时候就不用担心格式了。我提供了基本的替代代码 sn-p 从数据帧写入配置单元表,而不用担心格式。 Hive 原生支持 Parquet SerDe。请参考cwiki.apache.org/confluence/display/Hive/Parquet
那么说 Hive 原生支持 Parquet 但不支持 CSV 公平吗?【参考方案3】:
发生这种情况是因为 csv 的 HiveSerde 与 Spark 使用的不同。 Hive 默认使用 TEXTFORMAT 并且必须在创建表时指定分隔符。
一种选择是在从 spark 写入时使用 insertInto API 而不是 saveAsTable。在使用 insertInto 时,Spark 会将 Dataframe 的内容写入指定的表。但它要求数据框的架构与表的架构相同。列的位置在这里很重要,因为它忽略了列名。
Seq((5, 6)).toDF("a", "b").write.insertInto("t1")
【讨论】:
问题首先是创建 Hive 表。我同意如果它已经存在,您可以使用insertInto
。但我不知道有一种简单的方法可以从 Spark 中生成表(如果它尚不存在)。以上是关于从 Spark 写入 Hive 表,指定 CSV 作为格式的主要内容,如果未能解决你的问题,请参考以下文章
Spark SQL写入Hive,同分区overwrite,不同分区insert
在 Hive 表 hdfs 文件夹中写入文件并使其可用于从 Hive 查询
将 Spark Dataframe 写入 HDP2.6 中的 Hive 可访问表
.csv 不是 Select Hive Query 上的 SequenceFile 错误