はじめに
Athenaで作成済みのテーブル(パーティション化)について、Lmabdaからパーティション読み込みを行うクエリの実装中に躓いたことをまとめます。
Lambdaのランタイムはpythonになります。
起きたこと
下記コードのとおりパーティション読み込みクエリを実行するコードを実装して、Lambdaで実行したところエラー(例外)が発生しました。
同じクエリをAWSコンソールのAthenaから実行した場合、エラーにはなりませんでした。
# コード
table_name = 'table_a'
query = f'MSCK REPAIR TABLE {table_name};'
start_query_execution_response = athena.start_query_execution(
QueryString=query,
QueryExecutionContext={
'Database': os.getenv('ATHENA_DATABASE'),
},
ResultConfiguration={
'OutputLocation': os.getenv('ATHENA_OUTPUT')},
WorkGroup=os.getenv('ATHENA_WORKGROUP')]
)
execution_id = start_query_execution_response['QueryExecutionId']
# 実行完了までポーリングする必要があります
get_query_execution_response = athena.get_query_execution(
QueryExecutionId=execution_id)
# エラー内容
FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask
エラー原因
Lambdaの実行ロールの権限不足が上記エラーの原因でした。
今回のエラーが発生するまでは、権限不足の状態でLambdaを実行すると権限不足に関するエラーメッセージが出力されていたので、ポリシー設定は都度ググりながら対応していました。
不足していた権限
- default データベースに対する権限の付与
- Glue のデータベースおよびテーブルに対する権限不足
- ソースの S3 に対するの権限不足
default データベースに対する権限の付与
下記ステートメントが不足していました。
{
"Effect": "Allow",
"Action": [
"glue:GetDatabase",
"glue:CreateDatabase"
],
"Resource": [
"arn:aws:glue:ap-northeast-1:123456789012:catalog",
"arn:aws:glue:ap-northeast-1:123456789012:database/default"
]
}
Glue のデータベースおよびテーブルに対する権限不足
glue:GetDatabase および glue:BatchCreatePartition のみ定義しており、全てを網羅できていませんでした。
{
"Action": [
"glue:GetDatabase",
"glue:GetTable",
"glue:GetPartitions",
"glue:GetPartition",
"glue:BatchCreatePartition"
],
"Resource": [
"arn:aws:glue:ap-northeast-1:123456789012:catalog",
"arn:aws:glue:ap-northeast-1:123456789012:database/database_name",
"arn:aws:glue:ap-northeast-1:123456789012:table/database_name/table_name"
],
"Effect": "Allow"
}
ソースの S3 に対するの権限不足
s3:ListBucket
権限が不足していました。
{
"Action": [
"s3:DeleteObject*",
"s3:PutObject",
"s3:PutObjectLegalHold",
"s3:PutObjectRetention",
"s3:PutObjectTagging",
"s3:PutObjectVersionTagging",
"s3:Abort*",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::bucket_name",
"arn:aws:s3:::bucket_name/*"
],
"Effect": "Allow"
},
他のパーティション読み込み方法で対応
上記の例では、 MSCK REPAIR TABLE
によるパーティション読み込みを検討していましたが
ALTER TABLE ADD PARTITION
を利用することで上記エラーが発生せずに実装することができました。
パーティション読み込みを行う4つの方法
MSCK REPAIR TABLE
クエリALTER TABLE ADD PARTITION
クエリ- AWS Glue crawler
- パーティション射影(partition projection)
詳細は、Athena でのデータのパーティション化やユースケースに適したアプローチで、データカタログにパーティションをロードするを確認すると良いかと思います。
ALTER TABLE ADD PARTITION
クエリ
今回、Hiveスタイル形式のS3ソースを対象としていたので、
MSCK REPAIR TABLE
クエリを使用することを検討していました。
しかし、冒頭のエラーが発生し改めてパーティション読み込みについて調査したところ、 ALTER TABLE
を使用する方が良さそうだと今回は判断しました。
判断した理由
ALTER TABLE ADD PARTITION
クエリは、Hiveや非Hiveのどちらでも使用可能。MSCK REPAIR TABLE
クエリはパーティションの数が多くなる場合、クエリがタイムアウトする可能性があるため避けたい。実行毎に全てのパーティションが比較の対象となるため。- パーティション射影の場合、空のパーティションが多くなる可能性があるため避けたい。
下記はALTER TABLE ADD PARTITION
クエリのコードの一部です。
クエリの実行と結果取得は上記コードと同じロジックになります。
date
をパーティションの文字列とする場合は、おそらくエスケープする必要があります。
query = f"ALTER TABLE {table_name} ADD IF NOT EXISTS PARTITION (hogedate= '{hogedate}') LOCATION '{partition_path}';"
まとめ
エラーの原因が権限不足だったので、改めてしっかりとドキュメントを読み込み必要性があると感じました。一応、権限に関する公式ドキュメントを確認しながら実装していたのですが、所々足りませんでした。
パーティション読み込みにも複数アプローチがあるので、適宜使い分けられるようにしたいと思います。