🐝

謎のHive型「timestamp with local time zone」

4 min read

要約

  • Hiveには「timestamp」型の他に「timestamp with local time zone」型というのもあるよ
  • 名前の通り、ローカルのタイムゾーンに基づいて解釈・表示されるよ
  • TEXT FILE以外のフォーマットや、Trinoでは使えないよ
  • タイムゾーン('A`)メンドクセ

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標準)