Athenaでパーティションを楽に作成する方法
以前にAthenaの記事を投稿した時にパーティションの作り方として、Lambda関数からAthenaのクエリを実行する方法を紹介しました。
hi1280.hatenablog.com
このやり方よりも簡単にパーティションを作成する方法を今回は紹介します。
内容としては、パーティション射影という機能を使います。
こちらを使うと毎回パーティションを作る処理を実行することなく、自動的にパーティションを作ることが可能になります。
セットアップ
パーティション射影の機能を使うには、テーブルを作成するときに特別な設定を行う必要があります。
今回はALBのアクセスログに合わせたテーブルを作成することを題材にします。
テーブルを作成するクエリは以下のとおりです。
CREATE EXTERNAL TABLE `alb_logs_partition_projection`( `type` string, `time` string, `elb` string, `client_ip` string, `client_port` int, `target_ip` string, `target_port` int, `request_processing_time` double, `target_processing_time` double, `response_processing_time` double, `elb_status_code` string, `target_status_code` string, `received_bytes` bigint, `sent_bytes` bigint, `request_verb` string, `request_url` string, `request_proto` string, `user_agent` string, `ssl_cipher` string, `ssl_protocol` string, `target_group_arn` string, `trace_id` string, `domain_name` string, `chosen_cert_arn` string, `matched_rule_priority` string, `request_creation_time` string, `actions_executed` string, `redirect_url` string, `lambda_error_reason` string, `target_port_list` string, `target_status_code_list` string, `new_field` string) PARTITIONED BY ( `year` int, `month` int, `day` int) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' WITH SERDEPROPERTIES ( 'input.regex'='([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) ([^ ]*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^ ]*)\" \"([^s]+)\" \"([^s]+)\"(.*)') STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 's3://your-alb-logs-directory/AWSLogs/<ACCOUNT-ID>/elasticloadbalancing/ap-northeast-1' TBLPROPERTIES ( 'has_encrypted_data'='false', 'projection.enabled'='true', 'projection.day.digits'='2', 'projection.day.interval'='1', 'projection.day.range'='1,31', 'projection.day.type'='integer', 'projection.month.digits'='2', 'projection.month.interval'='1', 'projection.month.range'='1,12', 'projection.month.type'='integer', 'projection.year.digits'='4', 'projection.year.interval'='1', 'projection.year.range'='2020,2025', 'projection.year.type'='integer', 'storage.location.template'='s3://your-alb-logs-directory/AWSLogs/<ACCOUNT-ID>/elasticloadbalancing/ap-northeast-1/${year}/${month}/${day}' )
パーティション射影を設定するには、TBLPROPERTIESに設定していきます。
projection.enabledがtrueでパーティション射影を行うことを指定します。
今回のパーティションはyear、month、dayになります。それぞれにどのようにパーティションを作成するかを設定します。
たとえば、dayの場合について説明します。
projection.day.digitsで値が2桁であることを指定します。
projection.day.intervalでパーティション値の間隔を指定します。dayは1ずつ変化するため、1を指定します。
projection.day.rangeは値の最小値から最大値の範囲を指定します。dayの場合は、1から31になります。
projection.day.typeは値の型を指定します。ここでは、integerを指定して、値として整数値を期待します。
データがあるS3のロケーションとパーティションの値を関連づけるために、storage.location.templateを指定します。
${}の指定をすることで、パーティション値とS3のロケーションを関連づけることができます。
ここまでの内容で、year、month、dayのパーティション射影を設定すると、パーティションを自動で作成することができます。
動作確認
以下のようにパーティションを条件に加えて検索することで、パーティションが機能した状態でクエリが実行されます。
SELECT * FROM "default"."alb_logs_partition_projection" where year = 2021 and month = 2 and day = 27;
まとめ
今までAthenaでパーティションを作るのが面倒だと思っていましたが、パーティション射影を使うことでかなり楽ができそうです。