embulk-output-redshiftのタイムゾーンについて
embulk-output-redshiftでタイムゾーンがどう扱われるかを確認してみた。
Redshift側のタイムゾーン
UTC固定らしい。
検証の準備
テーブル
create table test1 ( id char(4), varchar_item varchar(20), integer_item int, numeric_item numeric(10,2), date_item date, timestamp_item timestamp, primary key (id) );
テストデータ
P001,あいうえお,123,123456.78,2015-05-20,2015-05-20 12:01:02+0900 P002,12345678901234567890,123456789,12345678.12,2015-12-31,2015-12-31 23:59:59+0900 P003,,,,,
yml
in: type: file path_prefix: 'data/data.csv' parser: charset: UTF-8 newline: CRLF type: csv delimiter: ',' columns: - {name: id, type: string} - {name: varchar_item, type: string} - {name: integer_item, type: long} - {name: NUMERIC_ITEM, type: string} - {name: date_item, type: timestamp, format: '%Y-%m-%d'} - {name: timestamp_item, type: timestamp, format: '%Y-%m-%d %H:%M:%S%z'} out: type: redshift host: xxx.redshift.amazonaws.com database: dev user: xxxxxxxx password: xxxxxxxx table: test1 mode: insert_direct iam_user_name: redshift access_key_id: XXXXXXXX secret_access_key: XXXXXXXXXXXXXXXX s3_bucket: xxxxxxxx
JSTで入れてみる
まず、クライアント側のタイムゾーンをJSTにして入れてみる。
embulk "-J-Duser.timezone=Asia/Tokyo" run redshift.yml
※Windowsの場合は""がいるが、Linuxの場合はいらないかも。
実行後にSELECTした結果(SQLクライアントのタイムゾーンはUTC)。
id | varchar_item | integer_item | numeric_item | date_item | timestamp_item |
---|---|---|---|---|---|
P001 | あいうえお | 123 | <null> | 2015-05-20 | 2015-05-20 12:01:02.0 |
P002 | 12345678901234567890 | 123456789 | <null> | 2015-12-31 | 2015-12-31 23:59:59.0 |
P003 | <null> | <null> | <null> | <null> | <null> |
UTCで入れてみる
次に、クライアント側のタイムゾーンをUTCにして入れてみる。
embulk "-J-Duser.timezone=UTC" run redshift.yml
実行後にSELECTした結果(SQLクライアントのタイムゾーンはUTC)。
id | varchar_item | integer_item | numeric_item | date_item | timestamp_item |
---|---|---|---|---|---|
P001 | あいうえお | 123 | <null> | 2015-05-20 | 2015-05-20 03:01:02.0 |
P002 | 12345678901234567890 | 123456789 | <null> | 2015-12-31 | 2015-12-31 14:59:59.0 |
P003 | <null> | <null> | <null> | <null> | <null> |
考察
Embulk内部では、時刻データをUTCで持っている。
embulk-output-redshiftは、入力データをS3上にファイル出力した後、COPYでRedshiftにロードする。
S3上の一時ファイルを確認したところ、クライアント側のタイムゾーンになっていた。
まとめると、こんな感じ。
クライアントのタイムゾーン | JST | UTC |
---|---|---|
CSVファイル | 23:59:59+0900 | 23:59:59+0900 |
Embulk内部 | 14:59:59 | 14:59:59 |
S3上の一時ファイル | 23:59:59 | 14:59:59 |
Redshift | 23:59:59 | 14:59:59 |
どうも、S3上の一時ファイルを出力する際に、クライアント側のタイムゾーンが反映されているようだ。
ソースを追ってみると、ファイルに書き出しているのはorg.embulk.output.postgresql.AbstractPostgreSQLCopyBatchInsertクラスのsetSqlTimestampメソッドだ。
public void setSqlTimestamp(Timestamp v, int sqlType) throws IOException { appendDelimiter(); writer.write(v.toString()); }
ここのTimestampは、java.sql.Timestamp型だ。
TimestampのtoStringを追ってみると、どうもクライアント側のタイムゾーンに応じてフォーマットされるようだ。
結論としては、クライアント側のタイムゾーンでの値が格納されるということだ。
embulk | 0.6.11 |
embulk-output-redshift | 0.3.0 |