AWS Athena のパーティションプロジェクション
2020 年 6 月に導入された Athena のパーティションプロジェクションにより、新しいパーティションを追加するために手動で MSCK REPAIR TABLE を実行する必要がなくなります。
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)にも対応します。
projection.year_month.range プロパティは UTC として扱われます。別のタイムゾーンを使いたい場合は、NOW+9HOURS のような形式で時差を明示的に指定する必要があります。
詳細は公式ドキュメントを参照してください。
AWSTemplateFormatVersion: "2010-09-09"Description: Stack for Athena partition projection sampleResources: 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_logsCloudFormation スタックをデプロイします。
aws cloudformation deploy \ --template-file stack.yml \ --stack-name athena-partition-projection-sampleデータのアップロード
続けて、テストデータを S3 バケットにアップロードします。
echo '{"id": 1, "message": "hello"}' > 2021-09.jsonecho '{"id": 2, "message": "world"}' > 2021-10.jsonaws 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/ファイルがアップロードされたことを確認します。
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/092021/10 パーティションも同様に動作します。
SELECT * FROM "sample"."sample_logs"WHERE year_month = '2021/10'LIMIT 10;期待される結果:
2 world 2021/10後片付け
この例で作成したリソースは、以下のコマンドで削除します。
aws s3 rm --recursive s3://athena-partition-projection-logsaws cloudformation delete-stack --stack-name athena-partition-projection-sampleまとめ
パーティションプロジェクションを有効化した Glue テーブルをデプロイしたところ、新しくアップロードされた year_month パーティションを、MSCK REPAIR TABLE の実行を挟むことなく Athena が即座にクエリできるとわかりました。projection.enabled: true と projection.year_month.range: 2021/09,NOW を組み合わせて設定すると、Athena は Glue カタログを参照する代わりに、範囲とフォーマットから有効なパーティションを数学的に計算します。そのため、新しい月のデータが届くたびにカタログのエントリを更新する必要がありません。この計算は storage.location.template が実際の S3 キーのレイアウトと一致していることに完全に依存しており、また NOW は UTC で評価されるため、ローカルの暦月に合わせたい範囲には NOW+9HOURS のような明示的なオフセットが必要です。そうしないと、タイムゾーンの差分の時間だけ、プロジェクションされたパーティションが実データからずれてしまいます。
Related posts
AthenaとKinesis Data FirehoseでS3のログをクエリする
Kinesis Data FirehoseでログをS3に流し込み、Athenaでクエリする。カスタムプレフィックスを使ってパーティションを自動登録させる方法。
Cognito User PoolsとOIDCでSlackサインインを実装する
Cognito user poolをOIDC経由でSlackと連携させ、"Sign in with Slack"をAmplifyでNext.jsアプリに組み込みます。
Lambda Web AdapterでFastAPIをAWS Lambdaにデプロイする
Lambda Web Adapterを使うと、FastAPIで書いたAPIバックエンドをコンテナのまま単一のLambda関数にデプロイできます。
API Gateway WebSocket:モック統合の実装
バックエンドのLambdaを一切使わず、モック統合のみでAPI Gateway WebSocket APIを構築し、あらかじめ用意されたレスポンスを返します。
CloudFront署名付きURL経由でS3にアップロードする
CloudFrontの署名付きURLを使えば、独自ドメイン経由でS3にアップロードできます。S3の直接の署名付きURLが使えない場合に有用です。
