Amazon Athenaのパーティションを理解する #reinvent

2016.12.06

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

コンニチハ、千葉です。Amazon Athenaを利用する上で重要になってくるパーティションについて書きたいと思います。

パーティションの重要性

Athenaでパーティションを指定することで、各クエリで特定の領域に対するスキャンを実行できるようになります。例えば、S3上のデータがs3://applog/YYYY/MM/DD/HHのような形でS3へ保存するとします。 パーティションを指定することで、検索時に特定の日付配下のデータだけスキャンすることができるので、パフォーマンスが向上します。また、スキャンするデータ量も減るため、コストも削減できます。

パーティションを設定する

パーティションを設定するには、テーブル作成時にPARTITIONED BYを指定して分割するキーを指定します。パーティションを追加する場合、以下の2つのシナリオがあります。

  1. S3上に格納されているデータが既にHiveフォーマットでパーティション化されている場合(例:s3://applog/dt=2009-04-12-13-00/)
  2. S3上に格納されているデータがパーティションを考慮されずに格納されている場合

1. S3上に格納されているデータが既にHiveフォマットでパーティション化されている場合

HiveフォーマットでS3データが格納されている場合のデータの例です

% aws s3 ls s3://elasticmapreduce/samples/hive-ads/tables/impressions/

    PRE dt=2009-04-12-13-00/
    PRE dt=2009-04-12-13-05/
    PRE dt=2009-04-12-13-10/
    PRE dt=2009-04-12-13-15/
    PRE dt=2009-04-12-13-20/
    PRE dt=2009-04-12-14-00/
    PRE dt=2009-04-12-14-05/
    PRE dt=2009-04-12-14-10/
    PRE dt=2009-04-12-14-15/
    PRE dt=2009-04-12-14-20/
    PRE dt=2009-04-12-15-00/
    PRE dt=2009-04-12-15-05/

上記の場合は、dt=で日付、日時、時間、分を指定しています。Athenaはこれをベースに検索範囲を絞り込んでスキャンします。

パーティションを利用する場合は、テーブルを作成時にPARTITIONED BYを指定します。

REATE EXTERNAL TABLE impressions (
    requestBeginTime string,
    adId string,
    impressionId string,
    referrer string,
    userAgent string,
    userCookie string,
    ip string,
    number string,
    processId string,
    browserCookie string,
    requestEndTime string,
    timers struct<modelLookup:string, requestTime:string>,
    threadId string,
    hostname string,
    sessionId string)
PARTITIONED BY (dt string)
ROW FORMAT  serde 'org.apache.hive.hcatalog.data.JsonSerDe'
    with serdeproperties ( 'paths'='requestBeginTime, adId, impressionId, referrer, userAgent, userCookie, ip' )
LOCATION 's3://elasticmapreduce/samples/hive-ads/tables/impressions/' ;

テーブル作成後に以下のクエリを実行します。パーティションを利用してロードできるようになります。

MSCK REPAIR TABLE impressions

クエリの実行は、以下のようにします。

SELECT dt,impressionid FROM impressions WHERE dt<'2009-04-12-14-00' and dt>='2009-04-12-13-00' ORDER BY dt DESC LIMIT 100

2. S3上に格納されているデータがパーティションを考慮されずに格納されている場合

ELB等のログがこれに当たります。

aws s3 ls s3://athena-examples/elb/plaintext/ --recursive

2016-11-23 17:54:46   11789573 elb/plaintext/2015/01/01/part-r-00000-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:46    8776899 elb/plaintext/2015/01/01/part-r-00001-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:46    9309800 elb/plaintext/2015/01/01/part-r-00002-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:47    9412570 elb/plaintext/2015/01/01/part-r-00003-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:47   10725938 elb/plaintext/2015/01/01/part-r-00004-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:46    9439710 elb/plaintext/2015/01/01/part-r-00005-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:47          0 elb/plaintext/2015/01/01_$folder$
2016-11-23 17:54:47    9012723 elb/plaintext/2015/01/02/part-r-00006-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:47    7571816 elb/plaintext/2015/01/02/part-r-00007-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:47    9673393 elb/plaintext/2015/01/02/part-r-00008-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:48   11979218 elb/plaintext/2015/01/02/part-r-00009-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:48    9546833 elb/plaintext/2015/01/02/part-r-00010-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:48   10960865 elb/plaintext/2015/01/02/part-r-00011-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:48          0 elb/plaintext/2015/01/02_$folder$

この場合は、テーブルに対してALTER TABLE ADD PARTITIONを実行して、パーティションを追加します。

ALTER TABLE elb_logs_raw_native_part ADD PARTITION (year='2015',month='01',day='01') location 's3://athena-examples/elb/plaintext/2015/01/01/'

注意点として、日付フォルダごとにパーティションを手動で追加していく必要があります。 例えば、2015/01/02のパーティションを追加する場合。

ALTER TABLE elb_logs_raw_native_part ADD PARTITION (year='2015',month='01',day='02') location 's3://athena-examples/elb/plaintext/2015/01/02/'

これは結構骨が折れます。JDBCを使って、自動で追加することを検討しましょう。また、パーティションはテーブルごとに20,000が上限になるので、これ以上追加する場合は上限緩和申請をする必要があります。

最後に

パーティションについての解説でした。パフォーマンス、コストに大きく影響する部分なのでAthenaを導入する場合は、事前に検討が必要ですね。

参考

http://docs.aws.amazon.com/athena/latest/ug/partitions.html http://docs.aws.amazon.com/athena/latest/ug/service-limits.html