AWS AthenaでPartitionを作る


BigQuery破産ならぬAthena破産

クエリでスキャンした容量毎に課金されるAthena。同じ課金方式(値段も一緒)のBigQueryでクエリの投げ方間違えて100万円溶かしたなどの話は有名ですよね。
Athenaでも同じことが起こりうる、というのでとても怖いです。
ちょっとしたミスがとんでもないことになる。 そこまでビビらなくてもいいですが、
とはいえ、怖いのは怖いものです。
とはいえ、使わないというのもどうかと思います。

ので、BigQueryと同じく、パーティションを作ってちゃんとスキャンされる範囲を制限してクエリを実行すれば
それなりに安全ということで、本家からも推奨されてます。

Athenaのパーティション

EMRなどでHiveを使ってS3にごにょごにょしてたのであれば、すでにHiveフォーマットでパーティショニングできてることもあります。
が、
我々がよくAthenaで見ようとするのはどちらかというとELBのアクセスログとかCloudfrontのアクセスログだったりするわけで。
それらはパーティショニングはできてないです。

なので、HiveのパーティショニングDDLでパーティションを作る必要があります。

ELBのログは、バケット配下に日付毎にディレクトリ(prefix)を作って、ちゃんと別れて格納されるので、それを使ってパーティションを分けるのが簡単だそうです。

テーブル作成

CREATE EXTERNAL TABLE table_name (
...
)
PARTITIONED BY (year string, month string, day string)
...

ここで設定したyear,month,dayを今後パーティションの条件として使っていきます。

Query

ALTER TABLE database_name.table_name ADD PARTITION (year='2016',month='08',day='28') location 's3://elb-access-log/AWSLogs/00000000000000/elasticloadbalancing/ap-northeast-1/2016/08/28/';

HiveのPartition作成構文と同じです。
これでパーティション1日分が作られます。1日分。

で、数年分作らなければいけないので、いっぺんに投げようとしたのですがなぜか通らず。

調べたら複数のADD PARTITIONをまとめて投げれるのはHive0.8からで、その前は一個一個投げないといけないみたいです。
参考-ApacheHive Language Manual DDL

ということはHive0.7以下の互換性ということなので、これ全部一個一個投げないと。。。
骨と心が折れます。
さてどうするか。

Athena JDBC

Athenaは公式JDBCを提供してるので、
それを使ってDDLを流し込めばいいのです。

私は2パターンで試しました。

  • 普通にJavaからループ文で投げる
  • SQL WorkbenchとかJDBCで繋げられるツールを使って、JDBCを読み込んで投げる

数が多いまたは規則性が簡単なのであれば前者で、
数が少ないまたは規則性もあんまりないのであれば後者でいいのではないかと思います。

終わりに

今後もS3はAWSのサービスを使っていく中でログの蓄積場所として一番使われるところということは変わらないと思うので、
Athenaの基本的な使い方とコストを抑える努力はやっていけたらなと思います。

こういう意識はAthenaに限らず、クエリ一本作るエンジニアみんなが意識できたらなと思いますね。

それではまた!