[新機能] Amazon Athena UNLOADコマンドによるCSV、Parquet、Avro、ORC、JSON出力をサポートしました!

2021.08.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

データアナリティクス事業本部コンサルティングチームの石川です。先日、Amazon Athenaが、UNLOADコマンドをサポートしました。SELECTクエリの結果をCSV、Parquet、Avro、ORC、JSONフォーマットでS3出力できるようになりました。本日は、UNLOADコマンドを実際に試してみます。

UNLOADコマンド

UNLOADコマンドの構文は、以下のとおりです。

UNLOAD (SELECT col_name[, ...] FROM old_table) 
TO 's3://my_athena_data_location/my_folder/' 
WITH ( property_name = 'expression' [, ...] )

WITH句の中にフォーマット(format)、区切り文字(field_delimiter)、圧縮タイプ(compression)、パーティション(partitioned_by)を指定します。

フォーマット(format)

format = 'file_format'

以下の出力フォーマットをサポートしています。

  • AVRO
  • PARQUET
  • ORC
  • JSON
  • TEXTFILE

区切り文字(field_delimiter)

field_delimiter = 'delimiter'

フォーマット(format)が、TEXTFILEの場合は、区切り文字(field_delimiter)を指定できます。デフォルトは0x01となります。

圧縮タイプ(compression)

compression = 'compression_format'

  • ORC:zlib(デフォルト)、lz4、snappy、zstd
  • Parquet:gzip(デフォルト)、snappy
  • 上記以外のフォーマット:gzip(デフォルト)

パーティション(partitioned_by)

partitioned_by = ARRAY[ col_name[,…] ]

パーティション(partitioned_by)指定したい場合は、パーティションするキーを配列で指定します。

WITH (format = 'TEXTFILE', partitioned_by = ARRAY['key1', 'key2'])

使用例

Avro出力

UNLOAD (SELECT * FROM "ssbgzdb"."customer") 
TO 's3://cm-temp-jp/customer/avro/' 
WITH (format = 'AVRO')

Parquet出力

UNLOAD (SELECT * FROM "ssbgzdb"."customer") 
TO 's3://cm-temp-jp/customer/parquet/' 
WITH (format = 'PARQUET',compression = 'SNAPPY')

ORC出力

UNLOAD (SELECT * FROM "ssbgzdb"."customer") 
TO 's3://cm-temp-jp/customer/orc/' 
WITH (format = 'ORC',compression = 'zstd')

JSON出力

UNLOAD (SELECT * FROM "ssbgzdb"."customer") 
TO 's3://cm-temp-jp/customer/json/' 
WITH (format = 'JSON')

TEXTFILE出力

デフォルトの区切り文字(field_delimiter)となります。ファイルのヘッダは、出力されません。

UNLOAD (SELECT * FROM "ssbgzdb"."customer") 
TO 's3://cm-temp-jp/customer/textfile/' 
WITH (format = 'TEXTFILE')

CSV出力したい場合は、field_delimiter = ','、TSV出力したい場合は、field_delimiter = '\t'を追加します。下記の例は、CSV出力の例です。

UNLOAD (SELECT * FROM "ssbgzdb"."customer") 
TO 's3://cm-temp-jp/customer/csv/' 
WITH (format = 'TEXTFILE',field_delimiter = ',')

TEXTFILE出力のパーティション指定

パーティション指定すると、指定したS3パスの直下に、カラム名ありパーティション形式のフォルダが作成され、フォルダの下にファイルが出力されます。

UNLOAD (SELECT * FROM "ssbgzdb"."customer") 
TO 's3://cm-temp-jp/customer/textfile_partitioned/' 
WITH (format = 'TEXTFILE', partitioned_by = ARRAY['c_mktsegment'])

注意点

エンジンバージョンは、Version2のみ

今日現在、デフォルトのエンジンバージョンは、Version2なので実質的にあまり問題にならないはずですが、念の為ご注意ください。

出力パスにS3オブジェクトが存在するとエラーになる

すでに出力パスにS3オブジェクトが存在するとエラーになります。データを洗い替えたい場合は、出力パスのS3オブジェクトを事前に削除する必要があります。

最大パーティション数は100以内

パーティションの数が100を超えると、エラーになります。そのため、パーティション数が100を超えるユースケースではパーティション指定(partitioned_by)の利用を避けたほうが良いでしょう。

パーティション指定できるカラムは最後のカラムのみ

パーティション指定できるカラムは最後のカラムのみです。

そのため、最後のカラム以外をパーティションキーに指定したい場合は、SELECTに指定するカラム名の最後にパーティションキーを指定することで回避することができます。

UNLOAD (SELECT c_custkey, c_name, c_address, c_region FROM "ssbgzdb"."customer") 
TO 's3://cm-temp-jp/customer/textfile_partitioned_xxx/' 
WITH (format = 'TEXTFILE', partitioned_by = ARRAY['c_region'])

Athenaは、障害が発生した場合、孤立したデータの削除をしません。そのため、UNLOADコマンドに指定するS3の出力パスはテンポラリなワーキングディレクトリを指定して、Athenaの実行が成功した後にターゲットディレクトリの削除とコピーするように実装したほうが良いのではないかと考えられます。

まとめ

UNLOADコマンドで、SELECTクエリの結果をCSV、Parquet、Avro、ORC、JSONフォーマットでS3出力できるようになりました。つまり、Athenaのようなサーバレスな仕組みを用いてSQLのみでELT (Extract、Load、Transform)ができるようになりました。今回のアップデートを利用することで、素早くコスト効率の良いAthenaでデータ加工ができるようになります。UNLOADコマンドによって出力されるファイルは、ファイル数が多い傾向がありますが、その点が問題なければ有効な選択肢になるはずです。

参考