Athena returns 拼花文件中时间戳字段的错误值

Athena returns wrong values for timestamp fields in parquet files

我在这里主要是重现我在 forum.aws 上看到的一个问题,希望 Whosebug 社区的 answers/explanations 比论坛上的讨论更彻底,更有启发性。

以下是我对这个问题的体验: 我使用 pandas 从 python 中的数据帧制作镶木地板文件,并使用 pandas.to_datetime 将 field/column 说生日作为 datetime64[ns]。这部分过程似乎完美无缺,因为我可以使用 pandas.read_parquet 读取镶木地板文件并得到我期望的结果,即在 datetime 中输入的日期。 但是,当我将所述镶木地板文件加载到 AWS 并在其上放置 athena table 时,读取相同的生日列会产生与镶木地板文件中的日期完全不匹配的垃圾日期。例如:

t = pandas.DataFrame([['Haiti',pandas.to_datetime('1804-01-01')]],columns=['Country','Independence'])
t.to_parquet("s3://<mybucket>/tmp/t.parquet")
|Country | Independence|
|--------|-------------|
|Haiti   | 1804-01-01  |
CREATE EXTERNAL TABLE IF NOT EXISTS default.mytable (
  `Country` string,
  `Independence` timestamp 
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
WITH SERDEPROPERTIES (
  'serialization.format' = '1'
) LOCATION 's3://<mybucket>/tmp/'
TBLPROPERTIES ('has_encrypted_data'='false');

SELECT * FROM "default"."mytable" limit 10;
|Country | Independence             |
|--------|--------------------------|
|Haiti   |-164033-12-18 00:00:00.000|

您可以强制 to_parquet 以 Athena 能够理解的格式写入 "coerce_timestamps":

t = pandas.DataFrame([['Haiti',pandas.to_datetime('1804-01-01')]],columns=['Country','Independence'])
t.to_parquet("s3://<mybucket>/tmp/t.parquet", coerce_timestamps='ms')
|Country | Independence|
|--------|-------------|
|Haiti   | 1804-01-01  |
CREATE EXTERNAL TABLE IF NOT EXISTS default.mytable (
  `Country` string,
  `Independence` timestamp 
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
WITH SERDEPROPERTIES (
  'serialization.format' = '1'
) LOCATION 's3://<mybucket>/tmp/'
TBLPROPERTIES ('has_encrypted_data'='false');

SELECT * FROM "default"."mytable" limit 10;
|Country | Independence          |
|--------|-----------------------|
|Haiti   |1804-01-01 00:00:00.000|