Impala 时间戳与 Hive 不匹配 - 时区问题?
Impala timestamps don't match Hive - a timezone issue?
我在 HDFS 中有一些事件日志数据,其原始格式如下所示:
2015-11-05 19:36:25.764 INFO [...etc...]
外部 table 指向此 HDFS 位置:
CREATE EXTERNAL TABLE `log_stage`(
`event_time` timestamp,
[...])
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
为了性能,我们想在 Impala 中查询这个。 log_stage
数据通过执行 Hive 查询插入 Hive/Impala Parquet-backed table:INSERT INTO TABLE log SELECT * FROM log_stage
。这是 Parquet table:
的 DDL
CREATE TABLE `log`(
`event_time` timestamp,
[...])
ROW FORMAT SERDE
'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
问题:Impala查询时,时间戳提前7小时:
Hive time: 2015-11-05 19:36:25.764
Impala time: 2015-11-06 02:36:25.764
> as.POSIXct("2015-11-06 02:36:25") - as.POSIXct("2015-11-05 19:36:25")
Time difference of 7 hours
注意:服务器的时区(从/etc/sysconfig/clock
开始)都设置为"America/Denver",目前比UTC晚7小时。
似乎 Impala 正在处理已经在 UTC 中的事件,错误地假设它们在 America/Denver 时间,并且又增加了 7 小时。
你知道如何同步时间以便 Impala table 与 Hive table 匹配吗?
Hive 以不同方式将时间戳写入 Parquet。您可以使用 impalad 标志 -convert_legacy_hive_parquet_utc_timestamps
告诉 Impala 在读取时进行转换。有关详细信息,请参阅 TIMESTAMP documentation。
This blog post有问题的简要说明:
When Hive stores a timestamp value into Parquet format, it converts local time into UTC time, and when it reads data out, it converts back to local time. Impala, however on the other hand, does no conversion when reads the timestamp field out, hence, UTC time is returned instead of local time.
impalad 标志告诉 Impala 在读取由 Hive 生成的 Parquet 中的时间戳时进行转换。它确实会产生一些小成本,因此如果这对您来说是个问题(尽管它可能很小),您应该考虑使用 Impala 编写时间戳。
在相关说明中,从 Hive v1.2 开始,您还可以使用此标志禁用时区转换行为:
hive.parquet.timestamp.skip.conversion
"parquet 的当前 Hive 实现将时间戳存储为 UTC,此标志允许在从其他工具读取 parquet 文件时跳过转换。"
这是作为 https://issues.apache.org/jira/browse/HIVE-9482
的一部分添加的
最后,不完全是时区,但为了 Parquet 文件上 Spark(v1.3 及更高版本)和 Impala 的兼容性,有这个标志:
spark.sql.parquet.int96AsTimestamp
https://spark.apache.org/docs/1.3.1/sql-programming-guide.html#configuration
由于https://issues.apache.org/jira/browse/IMPALA-2716
,请务必小心以上答案
就目前而言,最好的解决方法是不使用 TIMESTAMP 数据类型并将时间戳存储为字符串。
正如在
https://docs.cloudera.com/documentation/enterprise/latest/topics/impala_timestamp.html
您可以使用 ----use_local_tz_for_unix_timestamp_conversions=true
和 --convert_legacy_hive_parquet_utc_timestamps=true
来匹配 Hive 结果。
当您使用任何日期时间函数时,第一个确保它转换为本地时区。您可以将其设置为本文档中提到的 Impala 守护程序启动选项。
https://docs.cloudera.com/documentation/enterprise/5-6-x/topics/impala_config_options.html
我在 HDFS 中有一些事件日志数据,其原始格式如下所示:
2015-11-05 19:36:25.764 INFO [...etc...]
外部 table 指向此 HDFS 位置:
CREATE EXTERNAL TABLE `log_stage`(
`event_time` timestamp,
[...])
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
为了性能,我们想在 Impala 中查询这个。 log_stage
数据通过执行 Hive 查询插入 Hive/Impala Parquet-backed table:INSERT INTO TABLE log SELECT * FROM log_stage
。这是 Parquet table:
CREATE TABLE `log`(
`event_time` timestamp,
[...])
ROW FORMAT SERDE
'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
问题:Impala查询时,时间戳提前7小时:
Hive time: 2015-11-05 19:36:25.764
Impala time: 2015-11-06 02:36:25.764
> as.POSIXct("2015-11-06 02:36:25") - as.POSIXct("2015-11-05 19:36:25")
Time difference of 7 hours
注意:服务器的时区(从/etc/sysconfig/clock
开始)都设置为"America/Denver",目前比UTC晚7小时。
似乎 Impala 正在处理已经在 UTC 中的事件,错误地假设它们在 America/Denver 时间,并且又增加了 7 小时。
你知道如何同步时间以便 Impala table 与 Hive table 匹配吗?
Hive 以不同方式将时间戳写入 Parquet。您可以使用 impalad 标志 -convert_legacy_hive_parquet_utc_timestamps
告诉 Impala 在读取时进行转换。有关详细信息,请参阅 TIMESTAMP documentation。
This blog post有问题的简要说明:
When Hive stores a timestamp value into Parquet format, it converts local time into UTC time, and when it reads data out, it converts back to local time. Impala, however on the other hand, does no conversion when reads the timestamp field out, hence, UTC time is returned instead of local time.
impalad 标志告诉 Impala 在读取由 Hive 生成的 Parquet 中的时间戳时进行转换。它确实会产生一些小成本,因此如果这对您来说是个问题(尽管它可能很小),您应该考虑使用 Impala 编写时间戳。
在相关说明中,从 Hive v1.2 开始,您还可以使用此标志禁用时区转换行为:
hive.parquet.timestamp.skip.conversion
"parquet 的当前 Hive 实现将时间戳存储为 UTC,此标志允许在从其他工具读取 parquet 文件时跳过转换。"
这是作为 https://issues.apache.org/jira/browse/HIVE-9482
的一部分添加的最后,不完全是时区,但为了 Parquet 文件上 Spark(v1.3 及更高版本)和 Impala 的兼容性,有这个标志:
spark.sql.parquet.int96AsTimestamp
https://spark.apache.org/docs/1.3.1/sql-programming-guide.html#configuration
由于https://issues.apache.org/jira/browse/IMPALA-2716
,请务必小心以上答案就目前而言,最好的解决方法是不使用 TIMESTAMP 数据类型并将时间戳存储为字符串。
正如在 https://docs.cloudera.com/documentation/enterprise/latest/topics/impala_timestamp.html
您可以使用 ----use_local_tz_for_unix_timestamp_conversions=true
和 --convert_legacy_hive_parquet_utc_timestamps=true
来匹配 Hive 结果。
当您使用任何日期时间函数时,第一个确保它转换为本地时区。您可以将其设置为本文档中提到的 Impala 守护程序启动选项。
https://docs.cloudera.com/documentation/enterprise/5-6-x/topics/impala_config_options.html