AWS Athena のパーティションプロジェクション

AWS Athena のパーティションプロジェクション

2020 年 6 月に導入された Athena のパーティションプロジェクションにより、新しいパーティションを追加するために手動で MSCK REPAIR TABLE を実行する必要がなくなります。

Takahiro Iwasa
4 min read

2020 年 6 月に導入された Athena のパーティションプロジェクション を使うと、新しいパーティションを追加するために手動で MSCK REPAIR TABLE を実行する必要がなくなります。

バックエンドの構築

CloudFormation テンプレートで重要なのは、GlueTable 定義内の GlueTable.TableInput.Parameters セクション(27〜35 行目)です。このセクションでは、以下の重要なプロパティを使ってパーティションプロジェクションを有効化しています。

  • projection.enabled: パーティションプロジェクションを有効にします。
  • projection.year_month.format: パーティションの日付フォーマットを指定します。
  • projection.year_month.range: パーティションの範囲を定義し、オフセット付きの NOW(例: NOW+9HOURS)にも対応します。
💡 Tip

projection.year_month.range プロパティは UTC として扱われます。別のタイムゾーンを使いたい場合は、NOW+9HOURS のような形式で時差を明示的に指定する必要があります。

詳細は公式ドキュメントを参照してください。

stack.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: Stack for Athena partition projection sample
Resources:
S3:
Type: AWS::S3::Bucket
Properties:
BucketName: athena-partition-projection-logs
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
GlueDatabase:
Type: AWS::Glue::Database
Properties:
DatabaseInput:
Name: sample
CatalogId: !Ref AWS::AccountId
GlueTable:
Type: AWS::Glue::Table
Properties:
DatabaseName: !Ref GlueDatabase
CatalogId: !Ref AWS::AccountId
TableInput:
TableType: EXTERNAL_TABLE
Parameters:
classification: json
"projection.enabled": true
"projection.year_month.format": yyyy/MM
"projection.year_month.interval": 1
"projection.year_month.interval.unit": MONTHS
"projection.year_month.range": 2021/09,NOW
"projection.year_month.type": date
"storage.location.template": s3://athena-partition-projection-logs/${year_month}
StorageDescriptor:
Columns:
- Name: id
Type: int
- Name: message
Type: string
Location: !Sub s3://${S3}/
InputFormat: org.apache.hadoop.mapred.TextInputFormat
OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
Compressed: false
NumberOfBuckets: 0
SerdeInfo:
SerializationLibrary: org.openx.data.jsonserde.JsonSerDe
Parameters:
paths: id,message
StoredAsSubDirectories: false
PartitionKeys:
- Name: year_month
Type: string
Retention: 0
Name: sample_logs

CloudFormation スタックをデプロイします。

Terminal window
aws cloudformation deploy \
--template-file stack.yml \
--stack-name athena-partition-projection-sample

データのアップロード

続けて、テストデータを S3 バケットにアップロードします。

Terminal window
echo '{"id": 1, "message": "hello"}' > 2021-09.json
echo '{"id": 2, "message": "world"}' > 2021-10.json
aws s3 cp 2021-09.json s3://athena-partition-projection-logs/2021/09/
aws s3 cp 2021-10.json s3://athena-partition-projection-logs/2021/10/

ファイルがアップロードされたことを確認します。

Terminal window
aws s3 ls s3://athena-partition-projection-logs/2021/

データのクエリ

2021/09 パーティションからデータを取得し、プロジェクションが機能していることを確認します。

SELECT * FROM "sample"."sample_logs"
WHERE year_month = '2021/09'
LIMIT 10;

期待される結果:

1 hello 2021/09

2021/10 パーティションも同様に動作します。

SELECT * FROM "sample"."sample_logs"
WHERE year_month = '2021/10'
LIMIT 10;

期待される結果:

2 world 2021/10

後片付け

この例で作成したリソースは、以下のコマンドで削除します。

Terminal window
aws s3 rm --recursive s3://athena-partition-projection-logs
aws cloudformation delete-stack --stack-name athena-partition-projection-sample

まとめ

パーティションプロジェクションを有効化した Glue テーブルをデプロイしたところ、新しくアップロードされた year_month パーティションを、MSCK REPAIR TABLE の実行を挟むことなく Athena が即座にクエリできるとわかりました。projection.enabled: trueprojection.year_month.range: 2021/09,NOW を組み合わせて設定すると、Athena は Glue カタログを参照する代わりに、範囲とフォーマットから有効なパーティションを数学的に計算します。そのため、新しい月のデータが届くたびにカタログのエントリを更新する必要がありません。この計算は storage.location.template が実際の S3 キーのレイアウトと一致していることに完全に依存しており、また NOW は UTC で評価されるため、ローカルの暦月に合わせたい範囲には NOW+9HOURS のような明示的なオフセットが必要です。そうしないと、タイムゾーンの差分の時間だけ、プロジェクションされたパーティションが実データからずれてしまいます。

About the author

Takahiro Iwasa

Takahiro Iwasa

Software Developer

This blog shares technical notes from hands-on projects—architecture, implementation, and AWS service integrations.