謎のHive型「timestamp with local time zone」
要約
- Hiveには「timestamp」型の他に「timestamp with local time zone」型というのもあるよ
- 名前の通り、ローカルのタイムゾーンに基づいて解釈・表示されるよ
- TEXT FILE以外のフォーマットや、Trinoでは使えないよ
- タイムゾーン('A`)メンドクセ
timestamp with local time zoneが気になったきっかけ
- TrinoのHive ConnectorにはHive’s timestamp with local zone data type is not supported.との記載があり、「timestamp with local zone」型がHiveにあるような記載
- ところが、Hiveの日時関係ではTimestamp、Date、Intervalの三つの型のみが記載
- あれ、「timestamp with local time zone」って誰よ?
調べた
Hive-21350で実装中の機能で、Design Docsにtimestampとの説明・比較があります。
timestamp型はタイムゾーンに関する情報を持ちませんが(「Timestamps are interpreted to be timezoneless and stored as an offset from the UNIX epoch.」)、timestamp with local time zoneは環境のタイムゾーンの日時を考慮して、パース・表示されます。
例
上述のDesign Docにある例です。ワシントンD.C.(UTC-4)のタイムゾーンで「1969-07-20 16:17:39」を格納し、パリ(UTC+2)のタイムゾーンで読み込みする場合、
- timestampでは「1969-07-20 16:17:39」
- タイムゾーンの考慮がされない
- timestamp with local time zoneでは「1969-07-20 21:17:39」
- つまり、パリのタイムゾーン対応する時刻に変換されて表示
のようになります。
(2020/05時点)できること・できないこと
できる
- TextFile/SequenceFile/RCFileでの保存
できない
- ORC/Parquet/Avroでの保存
- Trinoでの扱い
やってみる
Hive 3.1.2です。
準備
timestamp型のtsと、timestamp with local timeがあるts_localの二つのカラムがある、Text Fileのテーブルを定義します。
hive> create table t (ts timestamp, ts_local timestamp with local time zone) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
hive> describe t;
ts timestamp
ts_local timestamp with local time zone('Asia/Tokyo')
タイムゾーンがJST
同じ日時の文字列入れます。
insert into t values ("2021-05-30 12:00:00", "2021-05-30 12:00:00");
SELECT結果も同じ日時ですが、timestamp with local time zoneの方(2列目)には「Asia/Tokyo」が表示されます。
hive> select * from t;
2021-05-30 12:00:00 2021-05-30 12:00:00.0 Asia/Tokyo
ちなみに、timestamp with local time zoneは、int(UNIX epoch)へのキャストが直にはできないようです。
hive> select int(ts), int(ts_local) from t;
1622376000 NULL
タイムゾーンをUTCにしてSELECT
タイムゾーンをUTCにした後Hiveを再起動し、同じSELECTを実行します。
- timestampの方は表示・UNIX epochがかわらず
- timestamp with localは対応するUTCの日時に変わる
ことがわかります。
hive> select * from t;
2021-05-30 12:00:00 2021-05-30 03:00:00.0 UTC
hive> select int(ts), int(ts_local) from t;
1622376000 NULL
保存されているファイル
- timestamp(一列目)の方はINSERT時の形式そのまま
- timestamp with local time zone(二列目)の方は、タイムゾーンの情報が付加
されて、文字列で保存されていることがわかります。
hadoop fs -cat hdfs://localhost:9000/user/hive/warehouse/t/000000_0/
2021-05-30 12:00:00,2021-05-30 12:00:00.0 Japan
他のフォーマットで保存
SequenceFile/RCFileでも保存できますが、ORCなどは駄目なようです。
Sequence File
hive> create table t_s (ts timestamp, ts_local timestamp with local time zone) stored as sequencefile;
hive> insert into t_s values ("2021-05-30 12:00:00", "2021-05-30 12:00:00");
hive> select * from t_s;
2021-05-30 12:00:00 2021-05-30 12:00:00.0 Japan
RCFile
hive> create table t_r (ts timestamp, ts_local timestamp with local time zone) stored as rcfile;
hive> insert into t_r values ("2021-05-30 12:00:00", "2021-05-30 12:00:00");
hive> select * from t_r;
2021-05-30 12:00:00 2021-05-30 12:00:00.0 Japan
ORC
CREATE自体はできます。
create table t_o (ts timestamp, ts_local timestamp with local time zone) stored as ORC;
しかし、INSERT時にエラーになります。
hive> insert into t_o values ("2021-05-30 12:00:00", "2021-05-30 12:00:00");
Query ID = m-kimura_20210530140134_0daff9f2-eef4-43ae-87a5-5498adc9fab0
Total jobs = 1
Launching Job 1 out of 1
Number of reduce tasks is set to 0 since there's no reduce operator
Job running in-process (local Hadoop)
org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.IllegalArgumentException: ORC doesn't handle primitive category TIMESTAMPLOCALTZ
余談
PostgreSQLなどには、timestamp with time zoneという型がありますが、Hiveではまだ未実装なようです。(SQL 2003標準)
Discussion