Amazon Redshift Spectrum 新たにサポートされたDATE型について試してみました
はじめに
Amazon Redshift Spectrumを利用して、Amazon S3上ののテキストファイルやカラムナフォーマットファイル(Parquet)に保存されているDATE型のデータをクエリできるようになりました。AWSではリージョン毎にGlueデータカタログでテーブル定義を共有していますが、クエリエンジンやファイルフォーマット組み合わせによって、サポートしてしているデータ型が異なります。登録されたテーブル定義を共有するAmazon Athenaの関係についても解説します。検証したRedshiftのBuildは1/26に更新された1.0.1657です。(東京リージョンではまだデプロイされていないかもしれません。)
- Amazon Redshift Spectrum Now Supports DATE Data Type (Posted On: Dec 21, 2017)
- Announcement: Amazon Redshift Maintenance (January 11th - January 25th, 2018)
サポートしているDATE型・TIMESTAMP型の形式
まず、どんな形式の文字列をDATE型・TIMESTAMP型のデータとして読み取れるかについて解説します。Amazon Redshiftのデータのロード(COPYコマンド)では、一般的な形式は自動認識してロードできますが、Amazon Redshift Spectrum や Amazon Athenaはスキーマオンリードなので、形式が限定されるのはやむを得ません。もし認識できない形式の文字列の場合は値がNULLになります。
DATE型
DATE型がサポートしている形式は、ISO 8601の拡張形式(YYYY-MM-DD
)です。ISO 8601の基本形式(YYYYMMDD
)やExcelでよく見る形式(YYYY/MM/DD
)はDATE型のデータとして読み込まれません。
TIMESTAMP型
TIMESTAMP型は、YYYY-MM-DD HH:MI:SS
形式です。例えば2018-01-23 03:13:42
は、ミリ秒が補完されて2018-01-23 03:13:42.000
となります。2018-01-23 03:13:42.123456
は、ミリ秒未満は切り捨てられて2018-01-23 03:13:42.123
となります。
以降では、DATE型は2017-07-07
、日時型(TIMESTAMP型)は2018-08-08 08:08:08
を用いて検証します。
テキストファイル(タブ区切り)の検証
検証用データ
データファイルは以下のタブ区切り文字列(.tsv)です。
1 22.22 33.33 44.44 gogo0123456789 rokuroku 2017-07-07 2018-08-08 08:08:08
テーブル定義
このデータに対して、Amazon Athenaから以下のDDLでテーブル定義します。カラムに対してプリミティブなさまざまなデータ型設定しています。パーティションキーにもDATE型を設定しています。
CREATE EXTERNAL TABLE `test_datatypes`( `id` int, `price` decimal(10,2), `profit` double, `discount` float, `name_full` varchar(100), `name_short` char(10), `order_date` date, `order_timestamp` timestamp) PARTITIONED BY ( `p_date` date) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 's3://my_bucket/test_datatypes' TBLPROPERTIES ( 'classification'='csv', 'delimiter'='\t', 'transient_lastDdlTime'='1516946597', 'typeOfData'='file')
Amazon Redshift Spectrum からクエリを実行
従来のBuild1.0.1582
では、「パーディションカラム以外DATE型はサポートしていないので、代わりにtimestamp型かvarchar型に定義してください」といったエラーが表示されます。
cmdb=> select version(); version -------------------------------------------------------------------------------------------------------------------------- PostgreSQL 8.0.2 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3), Redshift 1.0.1582 (1 row) cmawsteamdb=> select * from my_schema_db.test_datatypes; ERROR: Invalid DataCatalog response for external table "my_schema_db"."test_datatypes": Redshift does not support data type "date" for non-partitioning column "order_date". Try defining the column as "timestamp" or "varchar" instead.
執筆時点の最新版、Build1.0.1657
では、DATE型のカラム(order_date)が表示されています。パーティションカラム(p_date)もDATE型として参照できました。
cmawsteamdb=# select version(); version -------------------------------------------------------------------------------------------------------------------------- PostgreSQL 8.0.2 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3), Redshift 1.0.1657 (1 row) cmawsteamdb=# select * from my_schema_db.test_datatypes limit 1; id | price | profit | discount | name_full | name_short | order_date | order_timestamp | p_date ----+-------+--------+----------+----------------+------------+------------+---------------------+------------ 1 | 22.22 | 33.33 | 44.44 | gogo0123456789 | rokuroku | 2018-01-23 | 2018-01-23 03:13:42 | 2018-09-09 (1 row)
Amazon Athena からクエリを実行
もちろん、全く問題なくクエリが実行できました。
カラムナフォーマットファイル(Parquet)の検証
データソース test_datatypesテーブルからParquetのファイルの変換はAWS GlueをJobで生成しました。生成したファイルを同じくGlueのクローラでtest_datatypes_parquetテーブルを定義しています。
テーブル定義
Glueのクローラが生成したDDL以下のとおりです。
-- null: decimal(10,2), order_date, order_timestamp CREATE EXTERNAL TABLE `test_datatypes_parquet`( `id` int, `price` decimal(10,2), `profit` double, `discount` float, `name_full` string, `name_short` string, `order_date` date, `order_timestamp` timestamp) PARTITIONED BY ( `p_date` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 's3://my_bucket/test_datatypes_parquet/' TBLPROPERTIES ( 'CrawlerSchemaDeserializerVersion'='1.0', 'CrawlerSchemaSerializerVersion'='1.0', 'UPDATED_BY_CRAWLER'='test_datatypes_parquet', 'averageRecordSize'='358', 'classification'='parquet', 'compressionType'='none', 'objectCount'='1', 'recordCount'='2', 'sizeKey'='4296', 'typeOfData'='file')
Amazon Redshift Spectrum からクエリを実行
従来のBuild1.0.1582
では、「パーディションカラム以外DATE型はサポートしていないので、代わりにtimestamp型かvarchar型に定義してください」といったエラーが表示されます。
cmawsteamdb=> select version(); version -------------------------------------------------------------------------------------------------------------------------- PostgreSQL 8.0.2 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3), Redshift 1.0.1582 (1 row) cmawsteamdb=> select * from my_schema_db.test_datatypes_parquet limit 1; ERROR: Invalid DataCatalog response for external table "my_schema_db"."test_datatypes_parquet": Redshift does not support data type "date" for non-partitioning column "order_date". Try defining the column as "timestamp" or "varchar" instead.
執筆時点の最新版、Build1.0.1657
では、エラーメッセージに変化がありましたが、Parquetではエラーが発生しています。アナウンスがあったビルドはBuild 1.0.1636
なので、その後の更新で変化があったのかもしれません。
cmawsteamdb=# select * from my_schema_db.test_datatypes_parquet limit 1; ERROR: S3 Query Exception (Fetch) DETAIL: ----------------------------------------------- error: S3 Query Exception (Fetch) code: 15001 context: Task failed due to an internal error. File 'https://s3-external-1.amazonaws.com/my_bucket/test_datatypes_parquet/p_date=2018-09-09/part-00000-b23fbb42-1628-43ba-9773-78130e375eef.snappy.parquet has an incompatible Parquet schema for column 's3:// query: 1902645 location: dory_util.cpp:678 process: query1_73 [pid=10900] -----------------------------------------------
なお、Redshiftから以下のDDLを実行してテーブルを作成して、クエリを実行しましたが、動作に変化はありません。
CREATE EXTERNAL TABLE my_schema_db.test_datatypes_parquet_0 ( id integer, price decimal(10,2), profit double precision, discount float, name_full varchar(100), name_short char(10), order_date date, order_timestamp timestamp ) PARTITIONED BY ( p_date date) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 's3://my_bucket/test_datatypes_parquet/' TABLE PROPERTIES ( 'CrawlerSchemaDeserializerVersion'='1.0', 'CrawlerSchemaSerializerVersion'='1.0', 'UPDATED_BY_CRAWLER'='test_datatypes_parquet', 'averageRecordSize'='304', 'classification'='parquet', 'compressionType'='none', 'objectCount'='1', 'recordCount'='2', 'sizeKey'='3388', 'typeOfData'='file')
Amazon Athena からクエリを実行
Amazon AthenaのクエリエンジンであるPrestoは、カラムの型にDATE型やTIMESTAMP型をサポートしていませんので、NULLになります。
最後に
DATE型についてまとめますと、
- DATEのフォーマットは、
YYYY-MM-DD
形式 - TIMESTAMPのフォーマットは、
YYYY-MM-DD HH:MI:SS
形式 - CSVとTSVとParquetは、パーティションキーにDATE型のデータをAmazon Redshift Spectrum と Amazon Athenaで参照できる(従来通りの仕様)
- CSVとTSVは、カラムのDATE型のデータをAmazon Redshift Spectrum と Amazon Athena から参照できる(新たにサポート)
- Parquetは、カラムのDATE型のデータをAmazon Redshift Spectrum と Amazon Athena から参照できない(新たにサポートされているはずだが、確認できなかった)
- 今回はCSVとTSVとParquet以外の他のファイルフォーマット(実際にはSerde)については検証していない
以上の結果から、新たにCSVとTSVは、カラムのDATE型を定義して、データをクエリできる事が確認できました。一方、残念ながら、アナウンスにあったParquetのカラムのDATE型は、データの参照ができませんでした。以下のフォーラムを見ると、一度は1.0.1636
がリリースされたが、問題があり従来のBuild1.0.1582
に戻され、その後1/26に今回検証した1.0.1657
がリリースされたようです。そのような経緯があり1.0.1657
は当初のリリースノートの内容とは異なるのかもしれません。今後サポートされるのを期待して待ちたいと思います。
以上の結果から、Amazon RedshiftのテーブルデータをCSVやTSVにUNLOADしたデータであれば、Amazon Redshift Spectrum や Amazon Athenaから共通で参照できる事も確認できました。今回のDATE型のサポートやヘッダ行のスキップのサポートによって、データレイクへのマイグレーションにはずみがつきそうです。