STEP 16:Amazon Athena & Lambda

🔎 STEP 16: Amazon Athena & Lambda

サーバーレスクエリとイベント駆動処理で柔軟なデータ分析を実現しよう

📋 このステップで学ぶこと

  • Amazon Athenaとは(サーバーレスクエリ)
  • S3データの直接クエリ
  • パーティショニング戦略
  • Glue Catalogとの連携
  • AWS Lambda入門(サーバーレス処理)
  • S3トリガーの設定
  • 実践演習:S3のログ分析

🎯 このステップのゴール

このステップを終えると、S3のデータに直接SQLを実行し、イベント駆動で自動処理を実行できるようになります。AWSのサーバーレスサービスを組み合わせて、効率的なデータ分析パイプラインを構築しましょう。

🎯 1. Amazon Athenaとは

Athenaの基本

Amazon Athenaは、S3上のデータに直接SQLクエリを実行できるサーバーレスクエリサービスです。

💡 例え話:図書館で本を探す

【従来のデータ分析 = 本を全部借りて読む】 1. 図書館(S3)から本(データ)を全部借りる 2. 自分の部屋(サーバー)に持ち帰る 3. 1冊ずつ読んで必要な情報を探す 4. 返却する → 部屋(サーバー)を準備する必要がある → 全部持ち帰るので時間がかかる 【Athena = 図書館内で検索】 1. 図書館(S3)のカウンターで質問する 2. 司書(Athena)が本棚を検索 3. 必要なページだけコピーして渡してくれる 4. 部屋(サーバー)は不要! → サーバーレス=自分の部屋を持たない → 調べた分だけ料金を払う(従量課金) 【具体例】 「2025年1月の売上データを見たい」 ・従来:1TB全部ダウンロード → $100+時間 ・Athena:1月分10GBだけスキャン → $0.05

📝 Athenaの特徴

  • サーバーレス:インフラ管理不要、起動も即座
  • 従量課金:スキャンしたデータ量のみ課金($5/TB)
  • 標準SQL:Prestoベースの標準SQL(学習コスト低い)
  • 様々な形式に対応:CSV、JSON、Parquet、ORC、Avro等
  • Glue Catalog連携:メタデータを自動取得

AthenaとRedshiftの違い

💡 例え話:タクシー vs マイカー

【Athena = タクシー】 ・使いたい時だけ呼ぶ ・乗った分だけ料金(従量課金) ・車庫も保険も不要(サーバーレス) ・毎回配車を待つ(起動時間) → たまに使う人向け 【Redshift = マイカー】 ・毎日使うなら便利 ・固定費がかかる(時間課金) ・車庫(インフラ)の管理が必要 ・すぐに乗れる(常時起動) → 毎日使う人向け

📊 Athena vs Redshift 比較表

項目 Athena Redshift
インフラ サーバーレス クラスター管理必要
料金 クエリ課金($5/TB) 時間課金($0.25〜/時間)
データ保存 S3(別料金) クラスター内蔵
速度 やや遅い(数秒〜分) 高速(ミリ秒〜秒)
同時クエリ 自動スケール クラスター性能に依存
使用シーン アドホック分析
たまに実行
定期的な分析
頻繁に実行

💡 どちらを選ぶ?具体的な判断基準

【Athenaを選ぶ場合】 ・1日のクエリ回数が10回以下 ・データ探索、アドホック分析が中心 ・インフラ管理したくない ・コストを変動費にしたい 【Redshiftを選ぶ場合】 ・1日のクエリ回数が100回以上 ・定期レポート、ダッシュボードがある ・複雑なJOINや集計が多い ・サブ秒の応答速度が必要 【コスト比較例】 毎日100GBをスキャンする場合: ・Athena: $0.50/日 × 30日 = $15/月 ・Redshift: $0.25/時間 × 24時間 × 30日 = $180/月 → Athenaの方が12倍安い! ただし、1日1TBスキャンする場合: ・Athena: $5/日 × 30日 = $150/月 ・Redshift: $180/月 → Redshiftとほぼ同じ(速度重視ならRedshift)

🗄️ 2. S3データの直接クエリ

Athenaの使い方

📝 ステップ1:クエリ結果の保存先を設定

1. Athenaコンソールを開く 2. 「Settings」をクリック 3. 「Manage」をクリック 4. クエリ結果の保存先を設定 例: s3://my-bucket/athena-results/ 5. 「Save」をクリック ※ クエリ結果は毎回S3に保存される(課金対象外)

📝 ステップ2:データベースの作成

— データベース作成 CREATE DATABASE my_database; — データベース一覧を確認 SHOW DATABASES;

📝 ステップ3:テーブルの作成

— ======================================== — CSVファイルのテーブル作成 — ======================================== CREATE EXTERNAL TABLE sales ( sale_id INT, sale_date DATE, product_name STRING, amount DECIMAL(10,2), quantity INT ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’ — カンマ区切り STORED AS TEXTFILE — テキストファイル LOCATION ‘s3://my-bucket/data/sales/’ — S3のパス TBLPROPERTIES (‘skip.header.line.count’=’1’); — ヘッダー行をスキップ — ======================================== — Parquetファイルのテーブル作成(推奨) — ======================================== CREATE EXTERNAL TABLE sales_parquet ( sale_id INT, sale_date DATE, product_name STRING, amount DECIMAL(10,2), quantity INT ) STORED AS PARQUET — Parquet形式 LOCATION ‘s3://my-bucket/data/sales_parquet/’;

💡 EXTERNAL TABLEとは?

Athenaのテーブルは「EXTERNAL TABLE」(外部テーブル)です。データはS3に保存されたまま、Athenaはメタデータ(スキーマ情報)だけを管理します。テーブルを削除してもS3のデータは消えません。

📝 ステップ4:クエリの実行

— データを確認 SELECT * FROM sales LIMIT 10; — 集計クエリ SELECT sale_date, SUM(amount) as total_sales, COUNT(*) as order_count FROM sales GROUP BY sale_date ORDER BY sale_date DESC LIMIT 10; — 条件指定(WHERE句) SELECT * FROM sales WHERE sale_date BETWEEN DATE ‘2025-01-01’ AND DATE ‘2025-01-31’ AND amount > 1000; — 実行後、コンソール下部に表示される情報: — ・実行時間(例:2.5秒) — ・スキャン量(例:256MB) — ・料金(スキャン量 × $5/TB)

🗂️ 3. パーティショニング戦略

パーティショニングとは

Athenaでは、パーティショニングでスキャン量を削減し、クエリ性能を大幅に向上できます。

💡 例え話:図書館の本棚の整理

【パーティショニングなし = 全ての本が1つの棚】 「2025年1月の経済雑誌を探して」 → 棚にある全ての本を1冊ずつ確認 → 10万冊チェック、1時間かかる 【パーティショニングあり = 年/月で棚が分かれている】 「2025年1月の経済雑誌を探して」 → 「2025年」棚 → 「1月」棚 へ直行 → 1000冊だけチェック、1分で終わる 【Athenaでの効果】 パーティショニングなし:1TB全スキャン → $5、60秒 パーティショニングあり:10GBスキャン → $0.05、3秒 → コスト100分の1、速度20倍

💡 パーティショニングの効果(具体的数値)

【1年分の売上データ(1TB)を分析する場合】 パーティショニングなし: ├── 全データスキャン: 1TB ├── 料金: $5.00 └── 時間: 約60秒 year/month/dayでパーティショニング: ├── 1日分だけスキャン: 約3GB(1TB ÷ 365日) ├── 料金: $0.015 └── 時間: 約2秒 【削減効果】 ・コスト: 99.7%削減($5 → $0.015) ・時間: 97%削減(60秒 → 2秒)

パーティションテーブルの作成

📝 S3のフォルダ構造

【パーティションに対応したS3構造】 s3://my-bucket/data/sales_partitioned/ ├── year=2024/ │ ├── month=11/ │ │ ├── day=1/ │ │ │ └── data.parquet │ │ ├── day=2/ │ │ │ └── data.parquet │ │ └── … │ └── month=12/ │ └── … └── year=2025/ ├── month=1/ │ ├── day=1/ │ │ └── data.parquet │ └── … └── … 重要:フォルダ名は「カラム名=値」の形式! 例:year=2025、month=1、day=19
— ======================================== — パーティションテーブルの作成 — ======================================== CREATE EXTERNAL TABLE sales_partitioned ( sale_id INT, product_name STRING, amount DECIMAL(10,2), quantity INT ) PARTITIONED BY ( — パーティションカラムを指定 year INT, month INT, day INT ) STORED AS PARQUET LOCATION ‘s3://my-bucket/data/sales_partitioned/’; — ======================================== — パーティションの追加(方法1:手動) — ======================================== ALTER TABLE sales_partitioned ADD PARTITION (year=2025, month=1, day=19) LOCATION ‘s3://my-bucket/data/sales_partitioned/year=2025/month=1/day=19/’; — ======================================== — パーティションの追加(方法2:自動検出) — ======================================== — S3の全パーティションを自動で検出・追加 MSCK REPAIR TABLE sales_partitioned; — ======================================== — パーティション一覧の確認 — ======================================== SHOW PARTITIONS sales_partitioned;

パーティションを使ったクエリ

— ======================================== — 効率的なクエリ(パーティション指定あり) — ======================================== SELECT * FROM sales_partitioned WHERE year = 2025 AND month = 1 AND day = 19; — → 1日分のパーティションだけスキャン — → 高速・低コスト! — ======================================== — 非効率なクエリ(パーティション指定なし) — ======================================== SELECT * FROM sales_partitioned WHERE sale_date = ‘2025-01-19’; — sale_dateはパーティションカラムではない! — → 全パーティションをスキャン — → 遅い・高コスト — ======================================== — 効率的な範囲指定 — ======================================== SELECT * FROM sales_partitioned WHERE year = 2025 AND month = 1 AND day BETWEEN 1 AND 7; — 1週間分 — → 7日分のパーティションだけスキャン

⚠️ パーティショニングの注意点

  • 多すぎるパーティションはNG:10万以上は避ける(メタデータ管理が重くなる)
  • 小さすぎるパーティションもNG:1ファイル100MB以上推奨(細かすぎると効率低下)
  • WHERE句でパーティションカラムを必ず指定:指定しないと全スキャン
  • 新しいパーティションの追加を忘れない:MSCK REPAIR TABLEか手動追加

おすすめのパーティション設計

✅ パターン別おすすめ設計

【日次バッチデータ】 PARTITIONED BY (year INT, month INT, day INT) → 日単位でデータが増える場合 【時間単位のログデータ】 PARTITIONED BY (year INT, month INT, day INT, hour INT) → アクセスログ、イベントログなど 【地域×日付】 PARTITIONED BY (region STRING, year INT, month INT) → 地域別に分析することが多い場合 【カテゴリ×日付】 PARTITIONED BY (category STRING, year INT, month INT) → 商品カテゴリ別に分析することが多い場合

🔗 4. Glue Catalogとの連携

Glue Crawlerで自動テーブル作成

Glue Crawlerを使うと、Athenaのテーブルを自動作成できます。手動でCREATE TABLEを書く必要がありません。

💡 例え話:自動図書登録システム

【手動でテーブル作成 = 司書が1冊ずつ登録】 ・本のタイトル、著者、ページ数を確認 ・カタログに手入力 ・新しい本が入るたびに作業 → 時間がかかる、ミスが起きやすい 【Glue Crawler = 自動スキャンシステム】 ・本棚(S3)を自動スキャン ・バーコード(スキーマ)を自動読み取り ・カタログ(Data Catalog)に自動登録 ・新しい本も定期的に自動検出 → 手間なし、正確!

📝 Crawlerで自動テーブル作成の流れ

【手順】 1. Glue Crawlerを作成 ├── Name: sales-crawler ├── Data source: s3://my-bucket/data/sales/ └── Database: my_database 2. Crawlerを実行 ├── S3をスキャン ├── スキーマ自動検出(カラム名、型) ├── パーティション自動検出 └── Data Catalogに登録 3. Athenaで確認 ├── テーブルが自動作成されている! └── すぐにクエリ可能 【メリット】 ・CREATE TABLE文を書かなくていい ・スキーマ変更も自動で反映 ・パーティションも自動検出
— Glue Crawlerが作成したテーブルをAthenaでクエリ SELECT * FROM my_database.sales LIMIT 10; — パーティション情報も自動で設定されている SHOW PARTITIONS my_database.sales; — テーブルの詳細情報を確認 DESCRIBE FORMATTED my_database.sales;

⚡ 5. AWS Lambda入門

Lambdaとは

AWS Lambdaは、サーバーレスでコードを実行できるサービスです。イベント駆動で自動実行できます。

💡 例え話:自動販売機

【従来のサーバー = お店を開く】 ・店舗(サーバー)を借りる ・店員(アプリ)を雇う ・営業時間中は店員が待機 ・お客さんが来なくても人件費がかかる → 固定費が高い 【Lambda = 自動販売機】 ・機械だけ設置(コードだけアップロード) ・お客さん(イベント)が来たら自動で動く ・使った分だけ電気代(実行時間課金) ・24時間対応、スケール自動 → 使った分だけ、超低コスト 【具体例】 「S3にファイルがアップロードされたら処理する」 ・従来:サーバーを24時間起動 → $50/月 ・Lambda:1日100回実行 → $0.01/月 → 5000倍安い

📝 Lambdaの特徴

  • サーバーレス:インフラ管理不要
  • イベント駆動:S3、DynamoDB、API Gateway、CloudWatchなどのイベントで起動
  • 自動スケール:同時1000リクエストでも自動対応
  • 最大15分:短時間の処理向け
  • 超低コスト:100万リクエストで$0.20

Lambda関数の作成

import json def lambda_handler(event, context): “”” Lambda関数のエントリーポイント 引数: event: トリガーから渡されるデータ(S3イベント、APIリクエスト等) context: 実行環境の情報(残り時間、メモリ等) 戻り値: 辞書形式(APIの場合はHTTPレスポンス) “”” print(“Lambda function invoked!”) print(f”Event: {json.dumps(event)}”) # eventの中身を見て処理を分岐 # S3トリガーの場合、eventにバケット名やファイル名が入っている return { ‘statusCode’: 200, ‘body’: json.dumps(‘Hello from Lambda!’) }

S3トリガーの設定

💡 例え話:郵便受けセンサー

【S3トリガー = 郵便受けセンサー】 1. 郵便受け(S3バケット)にセンサー(トリガー)を設置 2. 郵便(ファイル)が届いたらセンサーが反応 3. 自動でロボット(Lambda)が起動 4. 郵便を処理(データ変換、通知など) 【使用例】 ・CSVがアップロードされたら自動でParquetに変換 ・画像がアップロードされたらサムネイル生成 ・ログファイルが届いたら異常検知して通知
import json import boto3 def lambda_handler(event, context): “”” S3にファイルがアップロードされたら自動起動 ファイル情報を取得してAthenaクエリを実行 “”” # ======================================== # 1. S3イベントからファイル情報を取得 # ======================================== # eventの中にS3の情報が入っている bucket = event[‘Records’][0][‘s3’][‘bucket’][‘name’] key = event[‘Records’][0][‘s3’][‘object’][‘key’] size = event[‘Records’][0][‘s3’][‘object’][‘size’] print(f”File uploaded: s3://{bucket}/{key}”) print(f”Size: {size} bytes”)

💡 S3イベント(event)の構造を詳しく解説

【S3イベントの全体構造】 event = { “Records”: [ ← ファイル情報の配列(複数ファイル対応) { ← Records[0] = 1つ目のファイル情報 “eventSource”: “aws:s3”, “eventTime”: “2025-01-15T10:30:00.000Z”, “eventName”: “ObjectCreated:Put”, “s3”: { ← S3関連の情報 “bucket”: { “name”: “my-bucket”, ← バケット名 “arn”: “arn:aws:s3:::my-bucket” }, “object”: { “key”: “data/sales/2025-01-15.csv”, ← ファイルパス “size”: 1234567, ← ファイルサイズ(バイト) “eTag”: “abc123…” ← ファイルのハッシュ値 } } }, { … } ← 2つ目以降のファイル(複数ファイル同時アップロード時) ] } 【コードの読み方】 bucket = event[‘Records’][0][‘s3’][‘bucket’][‘name’] ├───────────────┼────────────┼────────────┼──────────┘ │ │ │ └─ バケット名を取得 │ │ └─ bucket辞書にアクセス │ └─ s3辞書にアクセス └─ 1番目のファイル情報 図解: event ─→ Records ─→ [0] ─→ s3 ─→ bucket ─→ name │ │ └─→ object ─→ key │ │ └─→ size │ └─→ [1] ─→ …(2つ目のファイル) └─ 配列で複数ファイルに対応 【なぜ Records[0] なのか?】 ・S3バッチイベントでは複数ファイルが一度に通知される場合がある ・Records配列に複数のファイル情報が入る ・通常は1ファイルずつ処理するので [0] で最初のファイルを取得 ・複数ファイル対応したい場合は for ループで処理: for record in event[‘Records’]: bucket = record[‘s3’][‘bucket’][‘name’] key = record[‘s3’][‘object’][‘key’] # 各ファイルを処理…

💡 例え話:ネストした辞書 = 住所録

【住所録の例で理解しよう】 address_book = { “people”: [ # ← event[‘Records’] { # ← event[‘Records’][0] “name”: “田中太郎”, “address”: { # ← event[‘Records’][0][‘s3’] “city”: “東京”, # ← event[‘Records’][0][‘s3’][‘bucket’][‘name’] “street”: “渋谷1-1” } } ] } # 「田中太郎の住んでいる市」を取得 city = address_book[‘people’][0][‘address’][‘city’] # → “東京” # S3イベントも同じ構造! # 「アップロードされたファイルのバケット名」を取得 bucket = event[‘Records’][0][‘s3’][‘bucket’][‘name’] # → “my-bucket”
# ======================================== # 2. Athenaクエリを実行 # ======================================== athena = boto3.client(‘athena’) query = f””” SELECT COUNT(*) as record_count FROM my_database.sales WHERE sale_date = CURRENT_DATE “”” response = athena.start_query_execution( QueryString=query, QueryExecutionContext={‘Database’: ‘my_database’}, ResultConfiguration={ ‘OutputLocation’: ‘s3://my-bucket/athena-results/’ } ) query_execution_id = response[‘QueryExecutionId’] print(f”Query started: {query_execution_id}”) # ======================================== # 3. 結果を返す # ======================================== return { ‘statusCode’: 200, ‘body’: json.dumps(f’Processed {key}’) }

Lambdaトリガーの設定手順

📝 コンソールでの設定手順

【手順】 1. Lambda関数を作成 ├── Function name: process-sales-data ├── Runtime: Python 3.12 └── Handler: lambda_function.lambda_handler 2. S3トリガーを追加 ├── Trigger: S3 ├── Bucket: my-bucket ├── Event type: s3:ObjectCreated:Put(ファイル作成時) ├── Prefix: data/sales/(このフォルダのみ監視) └── Suffix: .csv(CSVファイルのみ対象) 3. IAM Roleに権限を付与 ├── AmazonS3ReadOnlyAccess(S3読み取り) ├── AmazonAthenaFullAccess(Athena実行) └── AWSGlueConsoleFullAccess(Data Catalog参照) 4. テスト ├── S3にファイルをアップロード ├── Lambdaが自動起動 └── CloudWatch Logsでログを確認

⚠️ Lambdaの注意点

  • 最大実行時間は15分:それ以上かかる処理はGlue ETL Jobを使う
  • メモリ制限:最大10GB(大きいファイルの処理は注意)
  • 同時実行制限:デフォルト1000(引き上げ可能)
  • コールドスタート:初回起動は数秒かかることがある

💪 6. 実践演習:S3のログ分析

演習 1 実践

S3に保存されたアクセスログをAthenaで分析し、異常値があればLambdaで通知する

要件:

  • アクセスログが毎時S3に保存される
  • Athenaでエラー率を集計
  • エラー率が5%を超えたらSNS通知

【解答例】

1. Athenaテーブル作成

— パーティション付きアクセスログテーブル CREATE EXTERNAL TABLE access_logs ( timestamp STRING, ip STRING, method STRING, path STRING, status_code INT, response_time INT ) PARTITIONED BY ( year INT, month INT, day INT, hour INT ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’ STORED AS TEXTFILE LOCATION ‘s3://my-bucket/logs/access/’; — パーティションを自動検出 MSCK REPAIR TABLE access_logs;

2. エラー率を計算するクエリ

— 時間帯別エラー率 SELECT year, month, day, hour, COUNT(*) as total_requests, SUM(CASE WHEN status_code >= 400 THEN 1 ELSE 0 END) as error_count, ROUND( CAST(SUM(CASE WHEN status_code >= 400 THEN 1 ELSE 0 END) AS DOUBLE) / COUNT(*) * 100, 2 ) as error_rate_percent FROM access_logs WHERE year = 2025 AND month = 1 AND day = 19 GROUP BY year, month, day, hour HAVING error_rate_percent > 5 — エラー率5%以上 ORDER BY hour DESC;

3. Lambda関数(S3トリガー)

import boto3 import time import json from datetime import datetime athena = boto3.client(‘athena’) sns = boto3.client(‘sns’) def lambda_handler(event, context): “”” S3にログファイルがアップロードされたら、 エラー率をチェックして異常値があれば通知 “”” # 現在時刻を取得 now = datetime.utcnow() # Athenaでエラー率を計算 query = f””” SELECT ROUND( CAST(SUM(CASE WHEN status_code >= 400 THEN 1 ELSE 0 END) AS DOUBLE) / COUNT(*) * 100, 2 ) as error_rate FROM access_logs WHERE year = {now.year} AND month = {now.month} AND day = {now.day} AND hour = {now.hour} “”” # クエリ実行 response = athena.start_query_execution( QueryString=query, QueryExecutionContext={‘Database’: ‘my_database’}, ResultConfiguration={ ‘OutputLocation’: ‘s3://my-bucket/athena-results/’ } ) query_execution_id = response[‘QueryExecutionId’] # クエリ完了を待つ(最大30秒) for _ in range(30): response = athena.get_query_execution( QueryExecutionId=query_execution_id ) status = response[‘QueryExecution’][‘Status’][‘State’] if status in [‘SUCCEEDED’, ‘FAILED’, ‘CANCELLED’]: break time.sleep(1) if status == ‘SUCCEEDED’: # 結果を取得 result = athena.get_query_results( QueryExecutionId=query_execution_id ) # エラー率を取得(2行目がデータ) if len(result[‘ResultSet’][‘Rows’]) > 1: error_rate_str = result[‘ResultSet’][‘Rows’][1][‘Data’][0].get(‘VarCharValue’, ‘0’) error_rate = float(error_rate_str) if error_rate_str else 0 print(f”Error rate: {error_rate}%”) # エラー率が5%を超えたら通知 if error_rate > 5.0: sns.publish( TopicArn=’arn:aws:sns:ap-northeast-1:123456789012:alerts’, Subject=’🚨 High Error Rate Alert’, Message=f”’ 警告: エラー率が閾値を超えました エラー率: {error_rate:.2f}% 閾値: 5% 時間: {now.strftime(‘%Y-%m-%d %H:00′)} UTC 対応をお願いします。 ”’ ) print(“Alert sent!”) return { ‘statusCode’: 200, ‘body’: json.dumps(‘Log analysis completed’) }

4. システム全体のフロー

【自動ログ監視システムのフロー】 ┌─────────────┐ │ Webサーバー │ │ (アクセスログ生成) └──────┬──────┘ │ 毎時アップロード ↓ ┌─────────────────────────────────────┐ │ S3 (s3://my-bucket/logs/access/) │ │ year=2025/month=1/day=19/hour=10/ │ └──────┬──────────────────────────────┘ │ S3イベント(ファイル作成) ↓ ┌─────────────┐ │ Lambda │ │ (自動起動) │ └──────┬──────┘ │ Athenaクエリ実行 ↓ ┌─────────────┐ │ Athena │ │ (エラー率計算) └──────┬──────┘ │ 結果取得 ↓ ┌─────────────┐ エラー率 > 5% ┌─────────────┐ │ Lambda │ ─────────────────→ │ SNS │ │ (判定) │ │ (メール送信) │ └─────────────┘ └─────────────┘ 【結果】 ・完全自動でログを監視 ・異常検知から通知まで約30秒 ・サーバー不要、低コスト運用

📝 STEP 16 のまとめ

✅ このステップで学んだこと

  • AthenaでS3データに直接SQLクエリ(サーバーレス、$5/TB)
  • パーティショニングでコスト99%削減、速度20倍向上
  • Glue Catalogとの連携で自動テーブル作成
  • Lambdaでイベント駆動のサーバーレス処理
  • S3トリガーで自動化パイプラインを構築

💡 重要ポイント

  • Athenaはアドホック分析に最適(たまにクエリする場合)
  • パーティショニングでスキャン量を大幅削減(必須テクニック)
  • Parquet形式でさらにコスト削減(CSV比で1/10)
  • Lambdaでイベント駆動の自動処理(最大15分)
  • AthenaとLambdaの組み合わせが強力

🎯 Part 3(AWS編)完了!

次のPart 4では、GCPのデータウェアハウス(BigQuery)を学びます。
STEP 17「BigQuery入門」で、Googleの強力なDWHを体験しましょう!

📝 理解度チェック

問題 1 基礎

AthenaとRedshiftの使い分けについて、それぞれ適したシーンを説明してください。

【解答】

Athena:

  • アドホック分析(たまにクエリ)
  • インフラ管理したくない
  • データがS3に保存されている
  • コストを変動費にしたい

Redshift:

  • 定期的な分析(毎日クエリ)
  • 高速性が重要
  • 複雑なJOINや集計が多い
  • 予測可能なコストが必要
問題 2 応用

Athenaでパーティショニングを使う利点を3つ挙げ、具体例を示してください。

【解答例】

  1. コスト削減:スキャン量が減るので料金が安くなる。例:1TBから10GBに削減 → $5から$0.05(100分の1)
  2. クエリ高速化:必要なパーティションだけスキャン。例:1年分のデータから1日分だけを読む(60秒→2秒)
  3. データ管理の簡素化:古いパーティションを簡単に削除。例:90日以上前のパーティションを自動削除
問題 3 応用

LambdaとGlue ETL Jobの違いを説明し、それぞれ適したユースケースを挙げてください。

【解答】

項目 Lambda Glue ETL Job
最大実行時間 15分 無制限(数時間OK)
処理エンジン 単一処理 Apache Spark(並列処理)
メモリ 最大10GB DPU単位(16GB〜)
適したケース 軽量処理、トリガー 大量データのETL

Lambdaに適したケース:S3イベントをトリガーにした通知、軽量なデータ変換、API呼び出し

Glueに適したケース:TB級データの変換、複雑なデータパイプライン、日次バッチ処理

❓ よくある質問

Q1: Athenaのクエリ料金はいくらですか?
$5/TBです。スキャンしたデータ量に応じて課金されます。例:
・10GBスキャン:$0.05
・100GBスキャン:$0.50
・1TBスキャン:$5.00

コスト削減のコツ:
1. パーティショニングでスキャン範囲を限定
2. Parquet形式を使用(CSV比で1/10のサイズ)
3. SELECT * を避けて必要なカラムだけ指定
Q2: Lambdaの実行時間制限はありますか?
はい、最大15分です。それ以上かかる処理は、Glue ETL Jobや他のサービスを検討してください。

Lambdaに向いている処理:
・S3トリガーでの軽量処理
・API呼び出し
・通知送信
・小規模データ変換

Lambdaに向かない処理:
・大量データの変換(→ Glue)
・長時間の機械学習(→ SageMaker)
Q3: Athenaで「HIVE_CURSOR_ERROR」が出ます
パーティションが正しく設定されていない可能性があります。対処法:

1. MSCK REPAIR TABLE テーブル名 を実行
2. パーティションを手動で追加
3. S3のフォルダ構造を確認(year=2025/month=01/ の形式)

Glue Crawlerを使うと、パーティションを自動検出してくれるので便利です。
Q4: LambdaからAthenaを呼び出すと結果を待てますか?
はい、ポーリングで待機できます。ただし注意点があります:

start_query_executionは非同期で、すぐに戻ります。結果を取得するには:
1. get_query_executionで状態を確認(SUCCEEDED/FAILED)
2. SUCCEEDEDになったらget_query_resultsで結果取得

注意:Athenaクエリが長時間かかる場合、Lambdaの15分制限に注意してください。長いクエリはStep Functionsで非同期処理を検討しましょう。
Q5: CSV形式とParquet形式でどのくらい差がありますか?
Parquetは約1/10のサイズ、クエリも高速です。

例:1000万行の売上データ
・CSV:500MB、クエリ15秒、料金$0.0025
・Parquet:50MB、クエリ3秒、料金$0.00025

Parquetのメリット:
1. 列指向形式なので必要なカラムだけ読み込める
2. 圧縮効率が高い
3. スキーマが内蔵されている

→ 可能な限りParquet形式を使いましょう!
📝

学習メモ

クラウドデータ基盤(AWS・GCP) - Step 16

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE