今日もプログラミング

IT技術とかプログラミングのこととか特にJavaを中心に書いていきます

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)。

idvarchar_iteminteger_itemnumeric_itemdate_itemtimestamp_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)。

idvarchar_iteminteger_itemnumeric_itemdate_itemtimestamp_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上の一時ファイルを確認したところ、クライアント側のタイムゾーンになっていた。

まとめると、こんな感じ。

クライアントのタイムゾーンJSTUTC
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