ForgeVision Engineer Blog

フォージビジョン エンジニア ブログ

Boto3+AthenaでS3のデータを取得する事前設定まとめ ― 汎用バケット・Iceberg・S3 Tables 3パターン対応

こんにちは、開発グループの寺田です。

本記事では、「Boto3+AthenaでS3のデータを取得する」ための事前準備を3パターンに整理してご紹介します。 自分の構成がどのパターンに該当するかを確認し、必要な設定だけを参照できるリファレンスとしてご活用ください。


はじめに

Boto3からAthenaを使ってS3上のデータを取得したい場合、S3のデータ構成によって必要な事前準備が異なります。

本記事では以下の3パターンを対象にします。

  • パターン① 汎用バケット(通常のCSV・JSONなど)
  • パターン② 汎用バケット上のIceberg Table
  • パターン③ テーブルバケット(S3 Tables)

「Athenaはコンソールで動いているからBoto3でも動くはず」と思って詰まるケースが多いのが、パターン③です。 パターン①②と比べて追加の設定が必要なため、本記事でまとめて整理します。


3パターンの全体像と比較表

まず、自分がどのパターンに該当するかを確認してください。

構成 Glue Data Catalog登録 Athenaデータソース登録 Lake Formation設定
① 汎用バケット(通常) ✅ 必要 ❌ 不要 ❌ 不要
② 汎用バケット(Iceberg) ✅ 必要(Iceberg用) ❌ 不要 ❌ 不要
③ テーブルバケット(S3 Tables) ✅ 必要(統合設定) ✅ 必要 ✅ 必要

本記事の前提 動作確認はデータレイク管理者ユーザーで実施しています。 Lake FormationのData permissionの設定については本記事では触れません。別ロールで実行する場合は権限設定が別途必要になります。

パターン①②はGlue Data Catalogへの登録が主な作業です。 パターン③はそれに加えてAthenaへのデータソース登録とLake Formationの設定が必要になります。


パターン①:汎用バケット(通常)

CSV・JSON・Parquetなど、一般的なフォーマットのデータをS3の汎用バケットに配置しているケースです。

Step 1:S3へのデータ配置とフォーマット確認

S3バケットにデータが配置されていることを確認します。 AthenaはS3上のデータをそのままクエリするため、データのフォーマットとパスを把握しておきます。

s3://your-bucket/your-prefix/data.parquet

Step 2:Glue Data Catalogにデータベースを作成する

AWSコンソールで AWS Glue を開き、左メニューから「データベース」を選択して「データベースを追加」をクリックします。
- Database type:Glue Databaseを選択
- Database Name:任意の名前(例:your_database
- Location:空欄でOK(S3パスはテーブル登録時に個別指定するため)

補足:Database type の3種類について

種別 用途
Glue Database 通常のデータベース。S3上のデータにテーブルを定義してAthenaからクエリできる状態を作る(パターン①②で該当)
Glue Database Resource Link 別のAWSアカウントやData Catalog上のデータベースへの参照リンク。クロスアカウント共有などで使用する
Glue Database in S3 Tables Federated Catalog S3 Tables(テーブルバケット)のネームスペースをGlue Data Catalogと紐づける際に使用する(パターン③で該当)

Step 3:Glue Data Catalogにテーブルを登録する

作成したデータベースを選択し、「テーブルを追加」からテーブルを作成します。

①Set table properties
設定例:
- Table Name:任意(例:your_table
- Database:Step 2で作成したデータベース
- Table format:Standard AWS Glue table (default)
- Data store:S3
- Data location is specified in:your account
- Include path:データが格納されているS3パス
- データ形式:CSV・JSON・Parquet など実際のフォーマットを選択
- スキーマ:カラム名と型を定義

②Choose or define schema
設定例:
- Schema:Define or upload schema
※スキーマを手動で定義するか、JSONファイルでアップロードする場合に選択
- Partition indexes:パーティション分割する場合は指定(今回は省略)

③確認画面で設定値に不備がないことを確認してテーブルを作成する

Step 4:Athenaで動作確認

AWSコンソールで Amazon Athena を開き、クエリエディタからクエリを実行して確認します。

SELECT * FROM your_database.your_table LIMIT 10;

コンソールで結果が返ることを確認できれば、Boto3からも同様に取得できます。 → 完全スクリプトはこちら

# Athenaクエリ実行
response = athena.start_query_execution(
    QueryString=query,
    QueryExecutionContext={
        'Database': database,  # 今回作成したデータベース
        'Catalog': catalog_name  # Glue Data Catalogを使用する場合は AwsDataCatalog を指定
    },
    ResultConfiguration={
        'OutputLocation': output_location
    }
)


パターン②:汎用バケット(Iceberg Table)

汎用バケット上にApache Icebergフォーマットで作成されたテーブルを使用するケースです。 Glue JobやAthenaでIcebergテーブルを作成した場合、Glue Data Catalogへの登録は自動で行われます。 手動登録が必要になるのは、既存のIcebergデータがS3に配置済みでカタログ未登録の場合などに限られます。

Step 1:Athenaで動作確認

SELECT * FROM your_database.your_iceberg_table LIMIT 10;

補足:エンジンバージョンについて
現在、新規ワークグループのデフォルトはバージョン3のため、通常は意識する必要はありません。
ただし古いワークグループを使い回している場合はバージョン2のままの可能性があります。
Icebergテーブルのクエリでエラーが出た際は、Athenaコンソールの「ワークグループ」→「設定」からエンジンバージョンを確認してみてください。

パターン②もBoto3から同様に取得できます。 → 完全スクリプトはこちら

# Athenaクエリ実行
response = athena.start_query_execution(
    QueryString=query,
    QueryExecutionContext={
        'Database': database,  # 自動登録されたデータベース(今回はpoc_icebergを設定)
        'Catalog': catalog_name  # Glue Data Catalogを使用する場合は AwsDataCatalog を指定
    },
    ResultConfiguration={
        'OutputLocation': output_location
    }
)


パターン③:テーブルバケット(S3 Tables)

Amazon S3 Tablesを使用しているケースです。 パターン①②と比較して、3つの追加設定が必要になります。

S3 TablesはIAMポリシーのみではデータにアクセスできず、Lake Formationを経由した認証が必須の仕組みになっています。そのためパターン①②と異なり、Step 3・Step 4のLake Formation設定が必要になります。

Step 1:S3 TablesとAWS分析サービスの統合を有効化する

⚠️ この設定はリージョンごとに初回のみ必要です。同一リージョン内の2つ目以降のテーブルバケットでは不要です。

AWSコンソールで Amazon S3 を開き、以下の手順で統合を有効化します。

  1. 左メニューから「テーブルバケット」を選択
  2. AWS 分析サービスとの統合の「統合を有効にする」をクリック

この設定により、S3 Tablesのテーブルバケット・名前空間・テーブルがGlue Data Catalogにs3tablescatalogとして登録され、 AthenaやGlue Jobから参照できるようになります。

Step 2:AthenaにS3 Tablesデータソースを登録する

AWSコンソールで Amazon Athena を開き、「データソース」から「データソースを作成」をクリックします。

  • データソースタイプ:AWS Glue Data Catalog
  • カタログ名s3tablescatalog/xxx(テーブルバケット名に合わせて指定)

⚠️ ここが最大のポイント AWSコンソールのAthenaでは、このカタログが内部的に補完されるため登録しなくても動作します。 しかしBoto3経由では明示的な登録が必須です。登録していないと CATALOG_NOT_FOUND エラーが発生します。

Step 3:Lake FormationのIAMアクセス制御を有効化する

AWSコンソールで AWS Lake Formation を開き、以下の手順で設定します。

  1. 左メニューの「管理」→「設定」を開く
  2. 「デフォルトの権限設定」セクションを確認する
  3. 以下の2つのチェックを外す
    • 「新しいデータベースに IAM アクセスコントロールを使用する」
    • 「新しいテーブルに IAM アクセスコントロールを使用する」

Step 4:Athenaで動作確認

コンソールのAthenaで、登録したデータソースを選択してクエリを実行します。

SELECT * FROM "your_namespace"."your_table" LIMIT 10;

パターン③もBoto3から同様に取得できます。 → 完全スクリプトはこちら

# Athenaクエリ実行
response = athena.start_query_execution(
    QueryString=query,
    QueryExecutionContext={
        'Database': database,  # 今回作成したデータベース(S3 Tablesの名前空間)
        'Catalog': catalog_name  # S3 Tablesカタログを明示的に指定(AwsDataCatalogではない)
    },
    ResultConfiguration={
        'OutputLocation': output_location
    }
)

Boto3での動作確認(3パターン共通)

上記の事前準備が完了したら、Boto3からAthenaを実行してデータを取得できます。 基本的なスクリプトは3パターン共通です。パターンごとの差分は catalog_namedatabase の指定箇所のみです。

import boto3
import time

athena = boto3.client('athena', region_name='ap-northeast-1')

# -----------------------------------------------
# パターンごとの設定値(ここだけ変更する)
# -----------------------------------------------

# パターン①:汎用バケット(通常)
catalog_name = 'AwsDataCatalog'
database     = 'your_database'
query        = 'SELECT * FROM your_table LIMIT 10'

# パターン②:汎用バケット(Iceberg)
# catalog_name = 'AwsDataCatalog'
# database     = 'your_database'
# query        = 'SELECT * FROM your_iceberg_table LIMIT 10'

# パターン③:テーブルバケット(S3 Tables)
# catalog_name = 's3tablescatalog/xxx'
# database     = 'your_database'
# query        = 'SELECT * FROM your_iceberg_table LIMIT 10'

# -----------------------------------------------
# Athenaクエリ実行(共通)
# -----------------------------------------------

output_location = 's3://your-athena-output-bucket/results/'

response = athena.start_query_execution(
    QueryString=query,
    QueryExecutionContext={
        'Database': database,
        'Catalog': catalog_name
    },
    ResultConfiguration={
        'OutputLocation': output_location
    }
)

query_execution_id = response['QueryExecutionId']
print(f'Query Execution ID: {query_execution_id}')

# クエリ完了まで待機
while True:
    result = athena.get_query_execution(QueryExecutionId=query_execution_id)
    state = result['QueryExecution']['Status']['State']
    if state in ['SUCCEEDED', 'FAILED', 'CANCELLED']:
        break
    print(f'Waiting... status: {state}')
    time.sleep(2)

if state != 'SUCCEEDED':
    reason = result['QueryExecution']['Status']['StateChangeReason']
    print(f'Query failed: {reason}')
else:
    # 結果取得
    results = athena.get_query_results(QueryExecutionId=query_execution_id)
    rows = results['ResultSet']['Rows']
    for row in rows:
        print([col.get('VarCharValue', '') for col in row['Data']])

⚠️ output_location はAthenaのクエリ結果出力先S3バケットを指定します。事前にバケットを用意しておいてください。


まとめ

3パターンの事前準備の違いを改めて整理します。

構成 Glue Data Catalog登録 Athenaデータソース登録 Lake Formation設定
① 汎用バケット(通常) ✅ 必要 ❌ 不要 ❌ 不要
② 汎用バケット(Iceberg) ✅ 必要(Iceberg用) ❌ 不要 ❌ 不要
③ テーブルバケット(S3 Tables) ✅ 必要(統合設定) ✅ 必要 ✅ 必要

パターンを見分けるポイント:

  • データがどのバケット種別に格納されているか(汎用 or テーブルバケット)
  • Icebergフォーマットを使っているか

関連記事

S3 Tables シリーズ
- S3 Tablesとは? 初めてのセットアップ & クエリ実行
- S3 Tablesのデータはどう更新する?INSERT・DELETE・UPDATE・MERGEを実践!
- 自分ではうまくいかなかったAmazon S3 Metadataの外部参照を、Kiroに設計させて検証する

Apache Iceberg Materialized View シリーズ
- Apache Iceberg Materialized Viewを試してみた① - Glue Job でMVを作る -
- Apache Iceberg Materialized Viewを試してみた② - MVを外部参照する -
- Apache Iceberg Materialized Viewを試してみた③ - Lake Formation で参照範囲を制御する -(公開予定)