Spark SQL 到 Hive 表 - 日期时间字段小时错误

Posted

技术标签:

【中文标题】Spark SQL 到 Hive 表 - 日期时间字段小时错误【英文标题】:Spark SQL to Hive table - Datetime Field Hours Bug 【发布时间】:2017-11-22 11:29:10 【问题描述】:

我遇到了这个问题:当我使用 spark.sql 在 Hive 中输入时间戳字段时 数据,时间奇怪地变成了21:00:00!

让我解释一下:

我有一个用 spark.sql 读取的 csv 文件。我读取文件,将其转换为数据框并将其存储在 Hive 表中。此文件中的字段之一是日期,格式为“2017 年 3 月 10 日”。我要输入的 Hive 中的字段是 Timestamp 格式(我使用这种数据类型而不是 Date 的原因是我想用 Impala 查询表,而 Impala 只有 Timestamp data type,所以它不是一种简单地将数据类型更改为日期的解决方案)

正如您从文档中看到的那样,Hive Timestamp 数据类型具有“YYYY-MM-DD HH:MM:SS”格式,因此在我将数据框输入到 Hive 表之前,我将日期值转换为适当的格式。

这是我的 Python 代码:

from datetime import datetime
from pyspark.sql.functions import udf

df = spark.read.csv("hdfs:/user/../MyFile.csv", header=True)

#Use a user defined function to convert date format
def DateConvert(x):
    x_augm = str(x)+" 00:00:00"
    datetime_object = datetime.strptime(x_augm,'%d/%m/%Y %H:%M:%S')
    return datetime_object.strftime('%Y-%m-%d %H:%M:%S')

DateConvert_udf = udf(DateConvert)

df= df.withColumn("Trans_Date", DateConvert_udf("Trans_Date"))

这会正确格式化时间戳。当我跑步时

df.select("Trans_Date").show(10, False)

我明白了:

+-------------------+
|Trans_Date         |
+-------------------+
|2017-10-16 00:00:00|
|2017-10-16 00:00:00|
|2017-10-16 00:00:00|
|2017-10-16 00:00:00|
|2017-10-16 00:00:00|
|2017-10-16 00:00:00|
|2017-10-16 00:00:00|
|2017-10-16 00:00:00|
|2017-10-16 00:00:00|
|2017-10-16 00:00:00|
+-------------------+

然后我像这样使用 Spark SQL 将数据导入 Hive

df.createOrReplaceTempView('tempTable')
spark.sql("insert into table db.table select * from tempTable")

我的问题是,当我转到 Hive 时,我的 Timestamp 字段的值如下:

2017-10-16 21:00:00

这很奇特!

提前感谢您的任何建议

【问题讨论】:

【参考方案1】:

这是将数据保存到具有 TIMESTAMP 数据类型的 Hive 表中时的常见问题。

当您将数据保存到 Hive 表中时,TIMESTAMP 值表示写入数据的主机的本地时区。

这里 2017-10-16 00:00:00 - UTC(默认)转换为 2017-10-16 21:00:00 - Hive 主机的本地时区。

为避免因意外时区问题而导致不希望的结果,在 Impala 中,时间戳在写入数据文件或从数据文件读取时都相对于 UTC 进行存储和解释。

您可以参考以下文档了解必要的配置设置。 https://www.cloudera.com/documentation/enterprise/5-9-x/topics/impala_timestamp.html#timestamp

【讨论】:

很好的解释,但哪种是避免它的正确方法?我发现添加像 00:00:00.0 这样的毫秒可以解决问题,我会进行编辑以包含它,但是还有其他方法吗? 我不认为添加毫秒可以解决问题。你试过了吗?【参考方案2】:

通过在 Spark 中创建时间戳时添加浮点数字,我能够解决这个问题。我只是将小时格式化为 HH:MM:SS.ff 格式,现在 Hive 表中的时间显示为 00:00:00,这正是我想要的。

我的新日期转换例程是:

def DateConvert(x):
    x_augm = str(x)+" 00:00:00.0"
    datetime_object = datetime.strptime(x_augm,'%d/%m/%Y %H:%M:%S.%f')
    return datetime_object.strftime('%Y-%m-%d %H:%M:%S.%f')  

【讨论】:

以上是关于Spark SQL 到 Hive 表 - 日期时间字段小时错误的主要内容,如果未能解决你的问题,请参考以下文章

Spark SQL - Hive“无法覆盖表”解决方法

从 spark sql 插入配置单元表

在 Spark SQL 中找不到 Hive 表 - Cloudera VM 中的 spark.sql.AnalysisException

Spark 2.3.0 SQL 无法将数据插入 hive hbase 表

Spark DataFrame vector 类型存储到Hive表

从 EMR 迁移到 AWS Glue 后在 Spark SQL 中找不到表