实际上,你提到的
文档存在问题。你可能指的是这段内容:
[OpenCSVSerDe] 识别 UNIX 格式下的 DATE 类型,比如 YYYY-MM-DD,作为 LONG 类型。
可以理解为,你将日期格式化为 YYYY-MM-DD。然而,在那句话中,该文档深深地误导了读者。当它提到 UNIX 格式时,实际上是指
UNIX Epoch Time。
根据 UNIX Epoch 的定义,你的日期应该是整数(因此文档中提到了 LONG 类型)。你的日期应该是自1970年1月1日以来过去的天数。
例如,你的示例CSV应该如下所示:
"i","d","f","s"
"1","17532","1.001","something great!"
"2","17533","2.002","something terrible!"
"3","17534","3.003","I'm an oil man"
然后,您可以运行完全相同的命令:
CREATE EXTERNAL TABLE test (i int, d date, f float, s string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
LOCATION 's3://mybucket/test/'
TBLPROPERTIES ("skip.header.line.count"="1");
如果您使用
select * from test
查询 Athena 表,您将获得以下结果:
i d f s
1 2018-01-01 1.001 something great!
2 2018-01-02 2.002 something terrible!
3 2018-01-03 3.003 I'm an oil man
类似的问题也影响了上述文档对于 TIMESTAMP 的解释:
[OpenCSVSerDe] 仅会识别指定为 UNIX 格式(例如 yyyy-mm-dd hh:mm:ss[.f...]
)的 TIMESTAMP 类型,将其解释为 LONG 类型。
这似乎表明我们应该将 TIMESTAMP 格式化为 yyyy-mm-dd hh:mm:ss[.f...]
。实际上并不是这样。事实上,我们需要再次使用 UNIX Epoch 时间,并且这一次使用从 1970 年 1 月 1 日午夜以来经过的毫秒数。
例如,考虑以下示例 CSV:
"i","d","f","s","t"
"1","17532","1.001","something great!","1564286638027"
"2","17533","2.002","something terrible!","1564486638027"
"3","17534","3.003","I'm an oil man","1563486638012"
以下是CREATE TABLE语句示例:
CREATE EXTERNAL TABLE test (i int, d date, f float, s string, t timestamp)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
LOCATION 's3://mybucket/test/'
TBLPROPERTIES ("skip.header.line.count"="1");
这将是执行
select * from test
查询的结果集:
i d f s t
--- ------------ ------- --------------------- -------------------------
1 2018-01-01 1.001 something great! 2019-07-28 04:03:58.027
2 2018-01-02 2.002 something terrible! 2019-07-30 11:37:18.027
3 2018-01-03 3.003 I'm an oil man 2019-07-18 21:50:38.012
DATE
实际上需要存储为整数,但是对于TIMESTAMP
并不知情。文档写得很糟糕,但是还是有道理的。 - Kirk BroadhurstROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
但无法使用ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
。 - broti