AWS Data Analytics Vol1本番運用|Athena×Glue×Lake Formation×Redshift

目次

なぜ Data Analytics Vol1 か — データレイク4層アーキテクチャ概観

AWS本番運用シリーズ Data Analytics Vol1 — 4層統合ガイド

本記事ではデータ分析基盤の本番運用を 4層スタック で解説します。

| 層 | サービス | 本記事での主題 |
|—|—|—|
| クエリ層 | Amazon Athena | Workgroup設計 / Partition Projection / CTAS / Federation |
| ETL層 | AWS Glue | Crawler / ETL Job Bookmark / Data Quality / Studio Visual ETL |
| ガバナンス層 | Lake Formation | TBAC権限モデル / Cross-Account / Governed Table |
| DWH層 | Redshift Serverless | RPU最適化 / Data Sharing / Federated Query / MV auto-refresh |

Data Analytics本番運用シリーズはVol1(本記事)を起点に、各サービスの深掘りと実運用ノウハウを展開します。

データレイク4層アーキテクチャとは

AWSのデータ分析基盤を本番運用で安定させるには、クエリ・ETL・ガバナンス・DWH の4層を疎結合に設計しながら統合的に運用する視点が欠かせません。各層が孤立するとコスト管理・権限管理・パフォーマンス最適化がサイロ化し、本番障害の温床になります。本記事では4層を一気通貫で設計・運用する実践知識を体系化します。

クエリ層 — Amazon Athena

AthenaはS3上のデータをサーバーレスに分析するインタラクティブクエリサービスです。スキャンしたデータ量(バイト)課金のため、Partition Projectionによるスキャン範囲絞り込みParquet/ORC形式への変換(CTAS)がコスト最適化の核心です。RDS/DynamoDB/CloudWatch LogsへのFederated Queryにより、外部データストアも一元的にクエリできます。Workgroupで部門・環境ごとにコスト・権限を分離することが本番設計の起点です。

クエリ実行のたびにクラスター管理が不要なため、アドホック分析から定期バッチレポートまで同一インフラで対応できます。ただしスキャン量の管理を怠ると想定外のコスト増を招くため、Workgroupのバイトスキャン上限設定とResult Reuseによる重複クエリキャッシュが本番必須設定です。

ETL層 — AWS Glue

GlueはApache Spark/PythonベースのサーバーレスマネージドETLサービスです。Job Bookmarkによる差分処理の冪等性担保が本番ETLパイプラインの安定性を支えます。Data Quality (DQDL) で入力データの品質を自動検証し、Studio Visual ETLでノーコード開発とGit管理を両立させます。

Crawlerのスキーマ推論とGlue Data Catalogの活用で、Athena・Redshiftとのメタデータ共有基盤を形成します。データソースがS3・RDS・DynamoDB・Kafkaなど多様な場合でも、Glueの統一インターフェースでETLジョブを一元管理できます。Worker typeとDPU割当の最適化がコストと処理速度のトレードオフを決定します。

ガバナンス層 — Lake Formation

Lake Formationはデータレイクのアクセス制御とメタデータ管理を一元化するサービスです。IAM直接制御では数百テーブル×数十チームの環境で権限管理が破綻します。Tag-Based Access Control (TBAC) でLF-Tagをリソースに付与し、プリンシパルへ「タグ条件付き」の一括権限付与を実現します。

Cross-Account Data SharingとGovernmed Tableによるトランザクション保証が、組織横断データ基盤の要件を満たします。Column-level SecurityとRow Filterによる細粒度アクセス制御で、PII(個人識別情報)を含むテーブルでも安全な共有が可能です。新テーブル追加時にタグを付与するだけで権限が自動継承される点が、大規模組織での管理コスト削減に直結します。

DWH層 — Redshift Serverless

Redshift Serverlessはコンピューティングリソースを自動スケールするフルマネージドDWHです。RPU (Redshift Processing Unit) のBase capacity設定・Usage Limitによるコスト上限・Materialized View auto-refreshによるBI高速化が本番最適化の3本柱です。

Data Sharingによりプロデューサー/コンシューマー間でライブデータをコピーなしで共有でき、Federated QueryでRDS/Auroraをシームレスに統合できます。従来のRedshift Provisionedと比較して、予測困難なワークロード変動に対して自動スケールが機能するため、初期キャパシティ設計の工数を大幅に削減できます。


対象読者と前提知識

本記事の対象読者:

  • Data Engineer: S3ベースのデータレイクを構築・運用し、ETLパイプラインを設計・監視している方
  • Analytics Engineer: データモデリングとクエリ最適化を担い、分析基盤のパフォーマンスを追求している方
  • Platform Engineer: データ基盤インフラとガバナンスを管掌し、セキュリティと運用効率を両立させたい方

前提知識:

分野必要な知識レベル
AWS基礎IAM/S3/VPCの基本操作を理解している
S3基本操作バケット設定・プレフィックス設計・ライフサイクルポリシーを扱える
SQL基礎SELECT/JOIN/GROUP BY/サブクエリを問題なく書ける
Python/PySparkGlueスクリプト読解に必要(基礎レベルで可)

本記事で到達できるゴール:

  1. Athena Workgroup設計とPartition ProjectionでS3スキャンコストを大幅削減する設計を実装できる
  2. Glue Job Bookmark + Data Qualityで再実行安全・品質検証済みのETLパイプラインを構築できる
  3. Lake Formation TBACで新テーブル追加時の権限自動継承を実現する組織横断ガバナンス体制を設計できる
  4. Redshift Serverless RPU最適化とFederated Queryでコスト予算内に収めながら分析速度を確保できる

本記事の読み方ガイド

本記事は4層スタックを §2〜§5 で順に解説し、§6〜§8 で実践力を強化する構成です。

セクション内容主な読者
§2 Amazon Athena 本番運用 ★山場1Workgroup / Partition Projection / CTAS / Federated Query / Cost Controlクエリコスト最適化担当
§3 AWS Glue 本番運用Crawler / Job Bookmark / Data Quality / Studio Visual ETLETLパイプライン設計・運用担当
§4 Lake Formation 本番運用 ★山場2TBAC / Cross-Account / Governed Table / Data Filterデータガバナンス・権限管理担当
§5 Redshift Serverless 本番運用RPU最適化 / Data Sharing / Federated Query / MV auto-refreshDWH・BI連携担当
§6 詰まりポイント7選本番でよく起きる7パターンの原因と解決策を図解障害対応・パフォーマンス改善担当
§7 アンチパターン演習5問アンチ→正解パターンのコード変換演習設計レビュー・スキルアップ
§8 まとめ + シリーズ案内全体振り返りと次のステップへの案内全読者

推奨読み方: 初読は §2→§3→§4→§5 の順に通して読むと、4層の依存関係と統合設計の全体像を把握できます。特定サービスの運用課題に直面している場合は、各セクションが独立して読めるよう設計しているため、対象セクションに直接アクセスしても支障ありません。

ハンズオン環境の準備: AWS CLIとPython(boto3)がインストール済みの環境を推奨します。Athena/Glue/Lake Formation/Redshift Serverlessの各サービスにアクセスできるIAMロールを事前に用意してください。本番環境での設定変更は必ずIAM権限の最小化とCloudTrail有効化を確認してから実施してください。

費用の目安: 本記事のコード例を動かす場合、クエリ・ETLジョブ・DWHクエリ合わせて数ドル程度の費用が発生します。AWS Free Tierで一部カバーできますが、Athena・Glue・Redshift Serverlessはそれぞれ別途課金されるため、学習用アカウントへのBudget Alert設定を推奨します。


4層統合の設計指針 — 疎結合と高凝集

4層スタックを本番で安定運用するには、各層が単独で障害に対して堅牢でありながら、層間の連携インターフェースを標準化する設計が重要です。

データフローの基本パターン:

S3 Raw Zone
  └─ Glue Crawler → Data Catalog (スキーマ自動登録)
└─ Glue ETL Job (Job Bookmark + Data Quality)
 └─ S3 Curated Zone (Parquet形式)
  ├─ Athena (インタラクティブクエリ / レポート)
  └─ Redshift Serverless (DWH / BI連携)

Lake Formation (全層の権限制御レイヤー)
  ├─ Data Catalog への Fine-grained Access Control
  ├─ S3 への Column/Row Level Security
  └─ Cross-Account Data Sharing の仲介

設計の優先順位:

  1. まずガバナンス層(Lake Formation)を設計する: 後から権限モデルを変更するとAthena・Glue・Redshiftのジョブが止まるリスクがある。TBAC設計を最初に確定させる。
  2. 次にETL層(Glue)のSchema evolutionポリシーを決める: S3のParquetスキーマが変わるとAthena・Redshiftのクエリが壊れる。GlueのMERGE SCHEMA設定とバックワード互換ルールを事前に策定する。
  3. クエリ層(Athena)のWorkgroup設計で境界を引く: 部門・環境・用途別のWorkgroupでコスト帰属を明確化してから、分析クエリの設計に着手する。
  4. DWH層(Redshift Serverless)はMV auto-refreshで鮮度を管理する: バッチETL完了後にMVが自動更新されるよう設計し、BI側のクエリは常にMVを参照させる。

アンチパターン: 早期Redshift依存の罠

Athena+Glue+S3で十分なユースケースにRedshiftを早期導入すると、RPU課金・Data Sharing設計・MV管理の複雑性が増します。月間クエリ量が少ない場合や、アドホック分析主体のチームはAthena+S3のみでスタートし、DWH要件が明確になった時点でRedshift Serverlessを追加する段階的採用が推奨です。


Amazon Athena 本番運用

Amazon Athena 本番運用アーキテクチャ
fig01: Amazon Athena 本番運用アーキテクチャ全体図 — Workgroup分離 / Partition Projection / CTAS / Federation

Athena Partition Projection — 本番運用の鉄則

Glue Catalogにパーティション登録せず、クエリ実行時にS3パスを自動推論する機能。数千パーティション超の場合にMSCK REPAIR TABLEの実行時間・コストを完全回避できる。date/enum/integer/injected の4型を正しく選定することが本番安定運用の鍵。

Workgroup設計 — コスト分離と権限境界の起点

AthenaのWorkgroupは、コスト・権限・設定を論理的に分離する単位です。デフォルトのprimary Workgroupに全ユーザーが混在すると、スキャン量の帰属が不明瞭になり、コスト最適化が困難になります。本番環境では最低でも環境別(prod/staging/dev)・用途別(adhoc/batch)の分離が必要です。

Workgroup作成の基本パターン:

# 本番バッチ用Workgroupを作成 (バイトスキャン上限: 10GB)
aws athena create-work-group \
  --name "prod-batch" \
  --configuration '{
 "ResultConfiguration": {
"OutputLocation": "s3://your-athena-results-prod/batch/",
"EncryptionConfiguration": {
  "EncryptionOption": "SSE_S3"
}
 },
 "EnforceWorkGroupConfiguration": true,
 "BytesScannedCutoffPerQuery": 10737418240,
 "PublishCloudWatchMetricsEnabled": true
  }' \
  --description "Production batch queries - 10GB scan limit per query"
# アドホック分析用Workgroup (1GB上限でコスト制御)
aws athena create-work-group \
  --name "adhoc-analysts" \
  --configuration '{
 "ResultConfiguration": {
"OutputLocation": "s3://your-athena-results-prod/adhoc/",
"EncryptionConfiguration": {
  "EncryptionOption": "SSE_KMS",
  "KmsKey": "arn:aws:kms:ap-northeast-1:123456789012:key/your-key-id"
}
 },
 "EnforceWorkGroupConfiguration": true,
 "BytesScannedCutoffPerQuery": 1073741824,
 "PublishCloudWatchMetricsEnabled": true
  }' \
  --description "Ad-hoc analyst queries - 1GB scan limit"

Workgroup設計の鉄則:

設定項目推奨設定理由
EnforceWorkGroupConfigurationtrueクライアント側の上書きを禁止しコスト制御を強制
BytesScannedCutoffPerQuery用途に応じて設定クエリ単位のコスト上限でコスト爆発を防止
PublishCloudWatchMetricsEnabledtrueスキャン量・クエリ数をCloudWatchで可視化
OutputLocationS3バケット+プレフィックス結果ファイルをWorkgroup別に分離して管理
EncryptionConfigurationSSE_S3またはSSE_KMSクエリ結果ファイルの暗号化を必須化

IAMポリシーでWorkgroup単位のアクセス制御を設定します。athena:StartQueryExecutionリソースにWorkgroup ARNを指定することで、特定Workgroupのみ使用可能なIAMロールを作成できます。


Partition Projection — スキャン最適化の最重要機能

Partition ProjectionはGlue Data Catalogにパーティションを登録せず、クエリ実行時にS3パスをDDL設定から自動推論する機能です。パーティション数が数千〜数百万に達する大規模ログ・イベントデータで特に効果を発揮します。MSCK REPAIR TABLEの実行コスト・時間を完全排除できます。

Partition Projectionの4型:

用途値の例
date日付範囲パーティションdt=2024-01-01dt=2024-12-31
enum固定値リストパーティションregion=ap-northeast-1,us-east-1
integer整数範囲パーティションshard=0shard=99
injectedクエリ時に値を注入WHERE句の値をそのままパスに埋め込む

date型の実装例 (S3プレフィックス: logs/year=YYYY/month=MM/day=DD/):

CREATE EXTERNAL TABLE access_logs (
  request_id STRING,
  client_ip  STRING,
  method  STRING,
  uri  STRING,
  status  INT,
  bytesBIGINT
)
PARTITIONED BY (
  year  STRING,
  month STRING,
  daySTRING
)
STORED AS PARQUET
LOCATION 's3://your-data-lake/logs/'
TBLPROPERTIES (
  'projection.enabled' = 'true',
  'projection.year.type'  = 'date',
  'projection.year.format'= 'yyyy',
  'projection.year.range' = '2023,NOW',
  'projection.year.interval' = '1',
  'projection.year.interval.unit' = 'YEARS',
  'projection.month.type' = 'date',
  'projection.month.format'  = 'MM',
  'projection.month.range'= '2023-01,NOW',
  'projection.month.interval'= '1',
  'projection.month.interval.unit' = 'MONTHS',
  'projection.day.type'= 'date',
  'projection.day.format' = 'dd',
  'projection.day.range'  = '2023-01-01,NOW',
  'projection.day.interval'  = '1',
  'projection.day.interval.unit' = 'DAYS',
  'storage.location.template'= 's3://your-data-lake/logs/year=${year}/month=${month}/day=${day}/'
);

enum型の実装例 (リージョン別パーティション):

CREATE EXTERNAL TABLE cloudfront_logs (
  date  STRING,
  time  STRING,
  edge_location STRING,
  bytes BIGINT,
  uriSTRING,
  statusINT
)
PARTITIONED BY (region STRING)
STORED AS PARQUET
LOCATION 's3://your-data-lake/cloudfront/'
TBLPROPERTIES (
  'projection.enabled' = 'true',
  'projection.region.type'= 'enum',
  'projection.region.values' = 'ap-northeast-1,us-east-1,eu-west-1,ap-southeast-1',
  'storage.location.template'= 's3://your-data-lake/cloudfront/region=${region}/'
);

Partition Projectionが効かないケースと対策:

  • rangeNOWは日次バッチでは機能するが、リアルタイムに近い更新にはNOWの精度を確認する
  • S3パスとDDLのstorage.location.templateが一致しない場合はクエリ結果が0行になる(デバッグはAthena実行計画を確認)
  • injected型はWHERE句に対象パーティション列の条件が必須。条件なしでクエリするとエラーになる

CTAS — Parquet変換とコスト最適化

CTAS (Create Table As Select) はクエリ結果をS3に書き出しながら新テーブルを定義する機能です。CSV→Parquet変換バケティングの2用途が本番で最も重要です。

CSVからParquetへのCTAS変換:

-- CSV形式の生データをParquet+Snappyに変換
CREATE TABLE access_logs_parquet
WITH (
  format  = 'PARQUET',
  write_compression = 'SNAPPY',
  external_location = 's3://your-data-lake/logs-parquet/',
  partitioned_by= ARRAY['year', 'month', 'day']
)
AS
SELECT
  request_id,
  client_ip,
  method,
  uri,
  status,
  bytes,
  year,
  month,
  day
FROM access_logs_csv
WHERE year = '2024';

Parquet+Snappy変換後のスキャン削減効果は典型的に70〜90%です。1TBのCSVデータが100〜300GBのスキャンになるケースも多く、Athenaの従量課金コストを劇的に削減できます。

バケティングによる結合高速化:

-- user_id でバケティング (JOIN高速化)
CREATE TABLE user_events_bucketed
WITH (
  format= 'PARQUET',
  bucketed_by = ARRAY['user_id'],
  bucket_count= 64,
  external_location = 's3://your-data-lake/user-events-bucketed/'
)
AS
SELECT * FROM user_events_raw;

バケティングは同一bucketed_by列でJOINする場合にシャッフルを回避し、クエリ時間を短縮します。bucket_countはデータサイズに応じて設定し、1バケットあたり128MB〜1GB程度が目安です。

CTASの注意点:

  • CTASで作成したテーブルはGlue Data Catalogに登録されるため、不要になったらDROP TABLE + S3削除の両方を実施する
  • partitioned_byに指定する列はSELECTの最後に配置する(Athenaのパーティション列順序ルール)
  • 大量データのCTASは実行時間が長く、DMLステートメントのタイムアウト(デフォルト30分)に注意

Federated Query — 外部データソースへの直接クエリ

Federated QueryはLambda Data Source Connectorを介して、S3以外のデータソース(RDS/Aurora/DynamoDB/CloudWatch Logs等)をAthenaから直接クエリする機能です。ETLパイプラインを構築せずに外部データと結合分析できます。

対応コネクタの主要一覧:

コネクタ対象データソースユースケース
AthenaMySQLConnectorRDS MySQL / Aurora MySQLアプリDBのマスターデータ参照
AthenaPostgreSQLConnectorRDS PostgreSQL / Aurora PostgreSQLトランザクションDBとS3の結合
AthenaDynamoDBConnectorDynamoDBNoSQLと分析クエリの統合
AthenaCloudWatchConnectorCloudWatch Logsログ分析とS3データの結合
AthenaRedshiftConnectorRedshiftRedshiftテーブルとの結合

RDS MySQL コネクタのデプロイ:

# AWS Serverless Application Repository からコネクタをデプロイ
aws serverlessrepo create-cloud-formation-change-set \
  --application-id arn:aws:serverlessrepo:us-east-1:292517598671:applications/AthenaMySQLConnector \
  --stack-name AthenaMySQLConnector \
  --capabilities CAPABILITY_RESOURCE_POLICY \
  --parameter-overrides \
 Name=AthenaMySQLConnector \
 SecretNameOrPrefix=mysql-prod \
 SpillBucket=your-spill-bucket \
 DefaultConnectionString="mysql://jdbc:mysql://your-rds-endpoint:3306/mydb"
-- Federated QueryでRDSのusersテーブルとS3のイベントログを結合
SELECT
  u.user_id,
  u.email,
  COUNT(e.event_id) AS event_count,
  SUM(e.revenue) AS total_revenue
FROM "lambda:AthenaMySQLConnector".mydb.users u
JOIN s3_event_logs e ON u.user_id = e.user_id
WHERE e.year = '2024' AND e.month = '01'
GROUP BY u.user_id, u.email
ORDER BY total_revenue DESC
LIMIT 100;

Federated Queryのパフォーマンス考慮点:

Federated QueryはLambda経由でデータをフェッチするため、大量データのフェッチはスピルバケット(S3)を経由しパフォーマンスが劣化します。以下の指針で設計します。

  • RDS側でインデックス済みの条件をWHERE句に含める(Connector側でプレディケートプッシュダウンが機能する)
  • フェッチ対象を絞り込んだサブクエリを使い、S3側との結合を最小化する
  • 大量データが必要な場合はGlue ETLでS3にレプリカを作成しAthenaから直接クエリする設計が現実的

Cost Control — スキャン量予測とResult Reuse

Athenaのコスト最適化はスキャン量の削減重複クエリの排除の2軸で実施します。

スキャン量予測クエリ:

Athenaはクエリ実行前にEXPLAINでスキャン量を確認できませんが、EXPLAIN ANALYZEでクエリプランと統計を取得できます。本番では以下のパターンでスキャン量を管理します。

-- スキャン量見積もり: S3Select + パーティション確認
SELECT COUNT(*) FROM access_logs
WHERE year = '2024' AND month = '01';
-- クエリ実行後にAthena ConsoleでデータスキャンMBを確認

-- 実行履歴からスキャン量ランキングを取得 (CloudWatch Logsより)
SELECT
  query_id,
  query,
  data_scanned_in_bytes / 1073741824.0 AS scanned_gb,
  total_execution_time_in_millis / 1000.0 AS exec_seconds
FROM information_schema.__internal_athena_query_history
ORDER BY data_scanned_in_bytes DESC
LIMIT 20;

Result Reuse (クエリ結果再利用):

2024年にGAとなったResult Reuse機能は、同一クエリの実行結果を最大60分間キャッシュします。同じレポートクエリが複数ユーザーから実行される場合、2回目以降はスキャン料金が発生しません。

# Workgroup単位でResult Reuseを有効化
aws athena update-work-group \
  --work-group "prod-batch" \
  --configuration-updates '{
 "ResultReuseConfiguration": {
"ResultReuseByAgeConfiguration": {
  "Enabled": true,
  "MaxAgeInMinutes": 60
}
 }
  }'
-- クエリ実行時にResult Reuseを有効化 (Workgroupデフォルトを上書き)
-- AthenaコンソールまたはAPI経由でQueryExecutionContextに指定
-- ResultReuseConfiguration: { ResultReuseByAgeConfiguration: { Enabled: true, MaxAgeInMinutes: 30 } }

Approximate Query (近似クエリ):

正確な集計が不要なケースでは近似関数を使い、スキャン量と実行時間を削減します。

-- 正確なCOUNT DISTINCT (フルスキャン)
SELECT COUNT(DISTINCT user_id) FROM user_events WHERE year = '2024';

-- 近似COUNT DISTINCT (HyperLogLog, 誤差2%以内)
SELECT approx_distinct(user_id) FROM user_events WHERE year = '2024';

-- パーセンタイル近似 (正確な計算より高速)
SELECT approx_percentile(response_time_ms, 0.95) AS p95_ms
FROM access_logs
WHERE year = '2024' AND month = '01';

Provisioned Capacity (2024年GA):

予測可能なワークロードにはProvisioned CapacityでDPUを予約し、オンデマンド課金よりもコストを最適化できます。1DPU=4時間単位の予約で、突発的なスキャン課金を固定費に変換します。バッチジョブが毎日決まった時間に実行される場合、オンデマンドより20〜40%のコスト削減が期待できます。


AWS Glue 本番運用

AWS Glue ETL 本番運用アーキテクチャ
fig02: AWS Glue ETL 本番運用アーキテクチャ — Crawler / Job Bookmark / Data Quality / Studio
%% Mermaid01: Glue ETL パイプライン全体フロー
graph LR
 S3_Raw[S3 Raw Zone] --> Crawler[Glue Crawler]
 Crawler --> Catalog[Data Catalog]
 Catalog --> ETL[Glue ETL Job]
 ETL --> DQ[Data Quality]
 DQ --> S3_Curated[S3 Curated Zone]
 ETL -.->|Job Bookmark| State[State Store]

Glue Job Bookmark — ETL冪等性の要

Job Bookmarkは処理済みデータの位置を記録し、次回実行時に未処理分のみをETLする。S3ソースの場合はファイルパス+タイムスタンプ、JDBCソースの場合はプライマリキー値で管理。リセット操作を誤ると全量再処理が走り、コスト爆発とデータ重複を引き起こす。

AWS Glue本番運用の核心は「信頼性あるETLパイプラインの設計と冪等性の確保」です。Crawler→Data Catalog→ETL Job→Data Qualityの4ステップを正しく組み合わせることで、本番障害の大半を予防できます。

Crawler 設計

スケジュール設計

スケジュール方式適用場面設定例
On-demand初期投入・手動トリガーAWS Console / Lambda連携
Cron式定期バッチcron(0 2 * * ? *) (毎日AM2時)
EventBridge連携S3 PutObject後即時起動S3イベント → EventBridge → Crawler

Crawlerのスケジュールは原則としてETL Jobの実行前に完了させ、Data Catalog更新を保証します。S3データが随時追加される場合はEventBridge連携でCrawlerをトリガーし、新規ファイル検出からカタログ反映まで5〜10分以内に抑えます。

スキーマ変更検知

本番環境では SchemaChangePolicyDeleteBehavior が特に重要です。DELETE_FROM_DATABASE にするとデータソース削除時にGlue Catalogからテーブル定義が消えます。

{
  "SchemaChangePolicy": {
 "UpdateBehavior": "UPDATE_IN_DATABASE",
 "DeleteBehavior": "LOG"
  },
  "RecrawlPolicy": {
 "RecrawlBehavior": "CRAWL_NEW_FOLDERS_ONLY"
  }
}
DeleteBehavior動作推奨場面
DELETE_FROM_DATABASEテーブルを自動削除開発環境のみ
DEPRECATE_IN_DATABASEテーブルをDEPRECATEDにマークステージング
LOGログのみ・削除しない本番環境推奨

Classifierカスタマイズ

デフォルト推論で型判定が誤る場合(数値カラムが文字列推論される等)、カスタムClassifierを定義します。

import boto3

glue = boto3.client('glue')

glue.create_classifier(
 CsvClassifier={
  'Name': 'custom-csv-with-header',
  'Delimiter': ',',
  'QuoteSymbol': '"',
  'ContainsHeader': 'PRESENT',
  'Header': ['user_id', 'event_type', 'timestamp', 'value'],
  'DisableValueTrimming': False,
  'AllowSingleColumn': False
 }
)

GrokClassifier(ログファイル)、XMLClassifier(構造化XML)、JsonClassifier(ネストJSON)も利用可能です。型推論が安定しない数値列は string 固定にし、AthenaDDLで明示的にキャストする方が本番安定性は高まります。

増分Crawl (RecrawlBehavior)

CRAWL_NEW_FOLDERS_ONLY を設定すると全量再スキャンを回避できます。S3のパーティション構造(year=YYYY/month=MM/day=DD)と組み合わせることで、新規パーティションのみスキャン対象になりCrawler実行時間を大幅に短縮できます。


ETL Job 設計

Worker Type と DPU 割当

Glue 4.0(2024年GA)では以下のWorker typeが利用可能です。

Worker TypevCPUMemory推奨ワークロード
G.1X416 GB標準ETL / 中規模データ (<100 GB)
G.2X832 GBメモリ集約型 / 大規模結合・集計
G.4X1664 GB大規模データ / ML特徴量生成 (Glue 4.0〜)
G.8X32128 GB超大規模 / Spark最適化ワークロード
Z.2X864 GBRay分散処理 / Python ETL高速化

DPU数は NumberOfWorkers × DPU_per_worker で計算します。まず G.1X×10 (10 DPU) から始め、実行時間とメモリ使用量をCloudWatch Metricsで計測して増減します。

# Glue Job実行
aws glue start-job-run \
  --job-name my-etl-job \
  --arguments '{"--JOB_RUN_ID":"run-20260525-001"}'

# ヒープ使用率確認
aws cloudwatch get-metric-statistics \
  --namespace Glue \
  --metric-name glue.driver.jvm.heap.usage \
  --dimensions Name=Type,Value=gauge Name=JobName,Value=my-etl-job \
  --start-time 2026-05-25T00:00:00Z \
  --end-time 2026-05-25T23:59:00Z \
  --period 300 \
  --statistics Average

Auto Scaling

--enable-auto-scaling フラグで有効化すると、指定した NumberOfWorkers を最大値として実際のデータ量に応じてWorkerが増減します。スケールアップのラグ(約3〜5分)があるため、データ量が安定している場合は固定Workers設定の方がコスト予測しやすいです。

glue.create_job(
 Name='auto-scaling-etl-job',
 Role='arn:aws:iam::123456789012:role/GlueServiceRole',
 Command={
  'Name': 'glueetl',
  'ScriptLocation': 's3://my-scripts/etl_job.py',
  'PythonVersion': '3'
 },
 GlueVersion='4.0',
 WorkerType='G.2X',
 NumberOfWorkers=20,
 DefaultArguments={
  '--enable-auto-scaling': 'true',
  '--job-bookmark-option': 'job-bookmark-enable'
 },
 Timeout=120
)

Timeout設定

デフォルトTimeoutは 2880分 (48時間) です。本番ETLでは処理時間実績の3〜5倍を上限として設定し、ハングアップを防止します。


Job Bookmark 詳解

状態管理の仕組み

ソースタイプトラッキング単位制約
S3ファイルパス + 最終更新時刻ファイル上書き時は再処理対象になる
JDBCプライマリキー値 (昇順カラム指定)job.bookmark.key 設定必須
Kinesis / Kafkaシーケンス番号ストリーミングモード専用
import sys
from awsglue.transforms import ApplyMapping
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

args = getResolvedOptions(sys.argv, ['JOB_NAME'])
sc = SparkContext()
glueContext = GlueContext(sc)
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

# transformation_ctx が Bookmark のキーとして機能する
datasource = glueContext.create_dynamic_frame.from_options(
 format_options={"withHeader": True, "separator": ","},
 connection_type="s3",
 format="csv",
 connection_options={
  "paths": ["s3://my-raw-bucket/events/"],
  "recurse": True,
 },
 transformation_ctx="datasource"
)

mapped = ApplyMapping.apply(
 frame=datasource,
 mappings=[
  ("user_id", "string", "user_id", "string"),
  ("event_type", "string", "event_type", "string"),
  ("timestamp", "string", "event_timestamp", "timestamp"),
  ("value", "string", "event_value", "double"),
 ],
 transformation_ctx="mapped"
)

glueContext.write_dynamic_frame.from_options(
 frame=mapped,
 connection_type="s3",
 format="parquet",
 connection_options={
  "path": "s3://my-curated-bucket/events/",
  "partitionKeys": ["event_type"]
 },
 transformation_ctx="datasink"
)

# Bookmark を更新・コミット。commit()前に失敗した場合は次回実行で再処理
job.commit()

リセット手順

# Bookmark 状態の確認
aws glue get-job-bookmark --job-name my-etl-job

# 特定 JobRun のみリセット
aws glue reset-job-bookmark \
  --job-name my-etl-job \
  --run-id jr_abcd1234567890

# 完全リセット (全量再処理 — ターゲット事前クリア必須)
aws glue reset-job-bookmark --job-name my-etl-job

リセット前に必ずターゲット(S3 Curated Zone / DWH)の重複データをクリアします。Bookmarkリセットのみではターゲットはクリアされず、データ重複が発生します。

Transformation Context と冪等性

同一ジョブ内で複数データソースを扱う場合、それぞれ異なる transformation_ctx を設定することで個別にBookmarkを管理できます。job.commit() はSparkのWriteアクション完了後に呼び出す設計が必須です。commit前に失敗した場合は次回実行で同一データを再処理し、冪等性が保証されます。


Data Quality (DQDL)

AWS Glue Data Quality(2024年GA)はDQDL(Data Quality Definition Language)でルールセットを定義し、ETLパイプラインにインライン品質チェックを組み込む機能です。

DQDL 構文

ruleset = """
Rules = [
 IsComplete "user_id",
 IsComplete "event_timestamp",
 IsUnique "event_id",
 ColumnValues "event_value" between 0 and 1000000,
 ColumnCount >= 4,
 RowCount > 100,
 Completeness "event_type" >= 0.99,
 Uniqueness "event_id" >= 0.999,
 ColumnCorrelation "purchase_amount" "order_quantity" > 0.7
]
"""

パイプラインへの組み込み

from awsglue.transforms import EvaluateDataQuality, SelectFromCollection

dq_result = EvaluateDataQuality().process_rows(
 frame=mapped,
 ruleset=ruleset,
 publishing_options={
  "dataQualityEvaluationContext": "my_dq_context",
  "enableDataQualityCloudWatchMetrics": True,
  "enableDataQualityResultsPublishing": True,
  "resultsS3Prefix": "s3://my-dq-results/",
 }
)

# 品質チェック通過レコードのみを後段へ渡す
passed_rows = SelectFromCollection.apply(dqs=dq_result, key="EvaluationContext")

EventBridge 連携

Data Quality評価結果はEventBridgeに自動送信されます。品質スコア劣化をSlack通知やPagerDutyアラートに接続できます。

{
  "source": ["aws.glue"],
  "detail-type": ["Data Quality Evaluation Results Available"],
  "detail": {
 "context": {
"contextType": ["GLUE_JOB"],
"jobName": ["my-etl-job"]
 },
 "resultDescription": {
"EvaluationMessage": [{"prefix": "FAIL"}]
 }
  }
}

品質スコア可視化

評価結果はGlue Data Quality UIのData Quality Scoreとして集計されます。CloudWatch Dashboardに glue.dataQuality.ruleOutcome メトリクスを追加することで、スコア推移をチームで継続監視できます。DQDL v2(Glue 4.0〜)ではanomaly detection(ColumnAnomaliesルール)による動的閾値チェックも利用可能です。


Studio Visual ETL

Glue Studio Visual ETLはノーコードでETLパイプラインを設計し、自動的にPySparkスクリプトを生成するビジュアルIDEです。

主要機能

機能説明
ノーコード設計ドラッグ&ドロップでSource→Transform→Targetを接続
スクリプト自動生成ビジュアル設計から完全なPySpark/Pythonシェルを生成
Git統合AWS CodeCommit/GitHub連携でバージョン管理
カスタムTransform独自PythonクラスをTransformコンポーネントとして登録・共有
Job Monitoringリアルタイム実行モニタリング・エラーハイライト

Git統合設定

aws glue update-job \
  --job-name studio-etl-job \
  --job-update '{
 "SourceControlDetails": {
"Provider": "AWS_CODE_COMMIT",
"Repository": "my-glue-scripts",
"Branch": "main",
"Folder": "jobs/studio-etl-job",
"AuthStrategy": "AWS_SECRETS_MANAGER",
"AuthToken": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:github-token"
 }
  }'

カスタムTransformの活用

組織横断で再利用可能なデータ変換ロジック(PIIマスキング、データ型正規化等)をカスタムコンポーネントとして共有できます。

from awsglue.transforms import DynamicTransform
from awsglue.dynamicframe import DynamicFrame
import pyspark.sql.functions as F

class PIIMaskingTransform(DynamicTransform):
 def process(self, frame, *args):
  df = frame.toDF()
  df = df.withColumn(
"email",
F.regexp_replace("email", r"(?<=.{2}).(?=.*@)", "*")
  )
  return DynamicFrame.fromDF(df, self.glue_ctx, "masked")

Lake Formation 本番運用

Lake Formation 権限モデル設計
fig03: Lake Formation 権限モデル全体設計 — TBAC / Column-level / Cross-Account / Governed Table

Lake Formation TBAC — 大規模権限管理の本命

数百テーブル×数十チームの環境でNamed Resource方式は管理破綻する。TBAC(Tag-Based Access Control)はLF-Tagをテーブル/カラムに付与し、プリンシパルに「このタグ値を持つリソースへのアクセス」を一括付与する。新テーブル追加時もタグ付けのみで権限が自動継承される。

AWS Lake Formationは「データに対するアクセス制御をIAMポリシーから分離し、データカタログ単位で統合管理する」データガバナンス基盤です。IAM Only方式からLake Formation方式への移行は段階的に実施します。

権限モデル全体設計

IAM → Lake Formation 移行パス

Phase 1: IAMOnly=false (Lake Formation有効化) + Super権限で既存IAMロールを維持
Phase 2: Named Resource方式でテーブル単位の権限をLFに移行
Phase 3: Tag-based方式(TBAC)に移行し、スケーラブルな権限管理を実現
Phase 4: IAM Passthrough無効化 → 完全LF管理
# Lake Formation 設定変更: IAM Only → LF管理へ
aws lakeformation put-data-lake-settings \
  --data-lake-settings '{
 "DataLakeAdmins": [
{"DataLakePrincipalIdentifier": "arn:aws:iam::123456789012:role/DataLakeAdmin"}
 ],
 "CreateDatabaseDefaultPermissions": [],
 "CreateTableDefaultPermissions": [],
 "AllowExternalDataFiltering": false
  }'

Named Resource vs TBAC の選択基準

方式適用規模管理コスト新リソース追加時
Named Resourceテーブル数 <50手動Grant必要
TBACテーブル数 ≥50 / チーム数 ≥10初期高・維持低タグ付けのみで自動継承
Hybrid混在環境・移行期Named→TBACへ段階移行

本番環境での推奨は Hybrid方式 です。既存リソースはNamed Resource方式を維持しつつ、新規データレイクエリアはTBACで管理します。


TBAC (Tag-Based Access Control)

TBACはLF-Tagをデータカタログ(Database/Table/Column)に付与し、プリンシパル(IAMロール/ユーザー/グループ)に「タグ値を持つリソースへのアクセス」を一括付与する方式です。

LF-Tag定義

# LF-Tag キーと許容値の定義
aws lakeformation create-lf-tag \
  --tag-key "DataClassification" \
  --tag-values '["public", "internal", "confidential", "restricted"]'

aws lakeformation create-lf-tag \
  --tag-key "BusinessDomain" \
  --tag-values '["sales", "marketing", "finance", "hr", "engineering"]'

aws lakeformation create-lf-tag \
  --tag-key "DataResidency" \
  --tag-values '["jp", "us", "eu", "global"]'

リソースへのタグ付け

aws lakeformation add-lf-tags-to-resource \
  --resource '{
 "Table": {
"DatabaseName": "sales_db",
"Name": "transactions"
 }
  }' \
  --lf-tags '[
 {"TagKey": "DataClassification", "TagValues": ["confidential"]},
 {"TagKey": "BusinessDomain", "TagValues": ["sales"]}
  ]'

プリンシパルへの権限付与

# 分析チームに sales/marketing ドメインの public/internal データへアクセスを付与
aws lakeformation grant-permissions \
  --principal '{"DataLakePrincipalIdentifier": "arn:aws:iam::123456789012:role/AnalyticsTeamRole"}' \
  --resource '{
 "LFTagPolicy": {
"ResourceType": "TABLE",
"Expression": [
  {"TagKey": "BusinessDomain", "TagValues": ["sales", "marketing"]},
  {"TagKey": "DataClassification", "TagValues": ["public", "internal"]}
]
 }
  }' \
  --permissions '["SELECT", "DESCRIBE"]' \
  --permissions-with-grant-option '[]'

式ベースフィルタ (Expression-based Filter)

Expression に複数タグを AND 条件で組み合わせます。OR条件は同一TagKeyに複数TagValuesを指定します。新テーブル追加時は対象タグを付与するだけで、登録済みのすべてのGrantが自動的に有効になります。

継承ルール

DatabaseにタグをつけるとデフォルトですべてのTableに継承されます。個別のTableに異なるタグを付与することで継承を上書き可能です。Columnレベルのタグは独立して設定します。

import boto3

lf = boto3.client('lakeformation')

# 権限一覧の確認
response = lf.list_permissions(
 principal={'DataLakePrincipalIdentifier': 'arn:aws:iam::123456789012:role/AnalyticsTeamRole'},
 resourceType='TABLE'
)

for perm in response['PrincipalResourcePermissions']:
 print(f"Resource: {perm['Resource']}")
 print(f"Permissions: {perm['Permissions']}")

Cross-Account 共有

Lake Formation Cross-Account共有は、プロデューサーアカウントのデータカタログリソースを、コンシューマーアカウントに安全に共有する機能です。

RAM (Resource Access Manager) 統合

# プロデューサー側: RAM で Share 作成
aws ram create-resource-share \
  --name "analytics-data-share" \
  --resource-arns "arn:aws:glue:ap-northeast-1:111111111111:database/sales_db" \
  --principals "222222222222" \
  --allow-external-principals

# コンシューマー側: RAM 招待を承認
aws ram accept-resource-share-invitation \
  --resource-share-invitation-arn "arn:aws:ram:ap-northeast-1:111111111111:resource-share-invitation/xxxxx"

外部アカウントへの Grant

# プロデューサー側: コンシューマーアカウントのロールに権限付与
aws lakeformation grant-permissions \
  --principal '{"DataLakePrincipalIdentifier": "arn:aws:iam::222222222222:role/DataConsumerRole"}' \
  --resource '{
 "Table": {
"CatalogId": "111111111111",
"DatabaseName": "sales_db",
"Name": "transactions"
 }
  }' \
  --permissions '["SELECT", "DESCRIBE"]'

Catalog Federation

コンシューマー側のGlue Catalogに「仮想テーブル」として外部アカウントのリソースを登録するFederation機能です。

aws glue create-database \
  --database-input '{
 "Name": "producer_sales_db",
 "FederatedDatabase": {
"Identifier": "arn:aws:glue:ap-northeast-1:111111111111:database/sales_db",
"ConnectionName": "cross-account-connection"
 }
  }'

Recipient権限

コンシューマーアカウントのLake Formation管理者はRecipientとして登録され、受け取った権限の範囲内でさらに下位ロールへGrant可能です(Grant with grant option)。クロスアカウント共有でよくある失敗は「RAM招待が未承認のまま権限付与しようとする」ケースです。RAM承認→LF Grant の順序を守ります。


Governed Table (ACID トランザクション)

Governed TableはLake Formation管理下のACID対応テーブルです。S3データレイク上でトランザクション保証とタイムトラベルクエリを実現します。

主要機能

機能説明備考
ACID Transaction複数ファイル書き込みのアトミック保証Glue ETL / Spark統合
Time Travel過去スナップショットへのクエリFOR SYSTEM_TIME AS OF
Storage Optimizer小ファイル統合・デッドファイル削除自動実行(設定要)
S3 Table Bucket統合S3 Tables (2024〜) との連携Apache Iceberg互換

Time Travel クエリ (Athena)

-- 昨日時点のスナップショットをクエリ
SELECT *
FROM sales_db.transactions
  FOR SYSTEM_TIME AS OF TIMESTAMP '2026-05-24 00:00:00'
WHERE event_date = '2026-05-24'
LIMIT 100;

-- バージョン番号指定
SELECT *
FROM sales_db.transactions
  FOR SYSTEM_VERSION AS OF 5
LIMIT 100;

Time Travelはデータ誤削除時のリカバリやデバッグ目的に活用できます。デフォルトのバージョン保持期間は7日間です。

Storage Optimizer 設定

aws lakeformation update-table-storage-optimizer \
  --catalog-id "123456789012" \
  --database-name "sales_db" \
  --table-name "transactions" \
  --storage-optimizer-config '{
 "compaction": {
"enabled": "true",
"target_file_size_mb": "512"
 },
 "retention": {
"enabled": "true",
"oldest_timestamp": "86400000"
 }
  }'

小ファイル問題(1MB未満のParquetファイルが数千個生成される状況)はAthenaScanコスト増大とクエリ遅延の原因です。Storage OptimizerのCompaction機能で定期的に統合します。


Data Filters (セル/カラム/行レベルセキュリティ)

Lake Formation Data Filtersは列・行レベルでのきめ細かなアクセス制御を実現します。TBACと組み合わせることで2段構えのガバナンスが実現できます。

Column Mask (カラムマスキング)

import boto3

lf = boto3.client('lakeformation')

lf.create_data_cells_filter(
 TableData={
  'TableCatalogId': '123456789012',
  'DatabaseName': 'customer_db',
  'TableName': 'customers',
  'Name': 'pii_masked_filter',
  'RowFilter': {
'FilterExpression': "TRUE"
  },
  'ColumnNames': ['customer_id', 'region', 'segment'],
  'ColumnWildcard': {}
 }
)

Row Filter (行レベルフィルタ)

# 特定リージョンのデータのみアクセス可能なFilterを作成
aws lakeformation create-data-cells-filter \
  --table-data '{
 "TableCatalogId": "123456789012",
 "DatabaseName": "sales_db",
 "TableName": "transactions",
 "Name": "jp_region_only",
 "RowFilter": {
"FilterExpression": "region = '"'"'ap-northeast-1'"'"'"
 },
 "ColumnWildcard": {}
  }'

# フィルタをプリンシパルに付与
aws lakeformation grant-permissions \
  --principal '{"DataLakePrincipalIdentifier": "arn:aws:iam::123456789012:role/JPAnalyticsRole"}' \
  --resource '{
 "DataCellsFilter": {
"TableCatalogId": "123456789012",
"DatabaseName": "sales_db",
"TableName": "transactions",
"Name": "jp_region_only"
 }
  }' \
  --permissions '["SELECT"]'

Cell-level Security の活用パターン

パターンRowFilterColumnWildcard/ColumnNames
リージョン分離region = 'jp'ColumnWildcard (全列)
PII列除外TRUE (全行)ColumnNames (非PII列のみ)
機密度分離classification != 'restricted'ColumnWildcard
複合条件dept = 'sales' AND year >= 2026ColumnNames (必要列のみ)

Data Filtersはポリシータグ(TBAC)との組み合わせが可能で、「特定タグを持つテーブルに対して、さらに行・列レベルの制御を追加する」という2段構えのガバナンスを実現できます。また、Glue JobやAthenのクエリに対してフィルタが透過的に適用されるため、アプリケーション側の変更は不要です。


Redshift Serverless 本番運用

Redshift Serverless 本番運用アーキテクチャ
fig04: Redshift Serverless 本番運用アーキテクチャ — RPU / Data Sharing / Federated Query / MV auto-refresh
%% Mermaid02: Data Analytics 4層スタック関係マップ (§8まとめ用)
graph TB
 subgraph Query["クエリ層"]
  Athena[Amazon Athena]
 end
 subgraph ETL["ETL層"]
  Glue[AWS Glue]
 end
 subgraph Gov["ガバナンス層"]
  LF[Lake Formation]
 end
 subgraph DWH["DWH層"]
  RS[Redshift Serverless]
 end
 S3[Amazon S3 Data Lake] --> Glue
 Glue --> S3
 S3 --> Athena
 LF -->|権限制御| Athena
 LF -->|権限制御| Glue
 LF -->|権限制御| RS
 S3 --> RS
 Athena -.->|Federated| RS
 RS -.->|Federated| Athena

Redshift Serverless RPU — コスト最適化の急所

RPU(Redshift Processing Unit)のBase capacityは8〜512の範囲で設定。過剰設定はアイドル時課金、過小設定はクエリタイムアウトを招く。Usage limitでRPU時間上限を設定し、Cooldown periodで自動スケールダウンまでの猶予時間を制御する。本番ではBase=32〜128、Usage limit=日次上限設定が推奨起点。

Redshift Serverless アーキテクチャ概観

Redshift Serverlessは Namespace (データ・ユーザー・IAMロールを管理) と Workgroup (コンピューティング設定・VPC・セキュリティを管理) の2層構造で構成される。Provisionedクラスターと異なりノード数・タイプの選択が不要で、RPU (Redshift Processing Unit) ベースの自動スケーリングが特徴。クエリが来ないとき自動的にコンピューティングがゼロにスケールダウンし、アイドルコストを削減できる。

概念役割主要設定項目
Namespaceデータプレーン管理データベース / スナップショット / IAMロール / KMS暗号化
Workgroupコンピューティング管理Base RPU / Max RPU / VPC / セキュリティグループ / Usage limit

同一Namespaceに複数Workgroupを紐づけることで、本番・開発・分析ワークロードを同一データセット上で分離実行できる。Data Sharingと組み合わせると、異なるアカウント・リージョンのWorkgroupからも同一データへアクセスが可能になる。

RPU (Redshift Processing Unit) 最適化

RPUは Redshift Serverless における計算能力の単位。1 RPUはCPU・メモリ・ネットワーク帯域を内包した抽象リソースであり、ユーザーはノードタイプを意識せず設定できる。

Base capacity — 起動ベースラインの決定

Base capacityはWorkgroupがリクエストを受けたときの初期投入RPU数。8〜512 RPUの範囲で8刻みに設定する。Base capacityが高いほど初期レスポンスが速くなるが、アイドル時のコストも増加する。

ワークロード分類推奨 Base capacity
開発・分析 (アドホッククエリ中心)8〜32 RPU
バッチ夜間処理 + BI ダッシュボード32〜64 RPU
リアルタイム報告 + 複数同時接続64〜128 RPU
大規模DWH (数百GB〜TB級)128〜512 RPU
-- Workgroup の Base capacity 確認
SELECT workgroup_name, base_capacity, max_capacity, status
FROM svv_redshift_serverless_workgroups;
# Base capacity の変更
aws redshift-serverless update-workgroup \
  --workgroup-name production-wg \
  --base-capacity 64

# 設定確認
aws redshift-serverless get-workgroup \
  --workgroup-name production-wg \
  --query 'workgroup.{BaseCapacity:baseCapacity,MaxCapacity:maxCapacity,Status:status}'

Usage limit — コスト上限ガード

Usage limitは期間内のRPU時間消費に上限を設定し、クエリ暴走によるコスト爆発を防ぐ。上限到達時のアクション (log/emit-metric/deactivate) を選択できる。

# 日次 RPU時間上限の設定 (例: 500 RPU-hours/day)
aws redshift-serverless create-usage-limit \
  --resource-arn arn:aws:redshift-serverless:ap-northeast-1:123456789012:workgroup/production-wg \
  --usage-type serverless-compute \
  --amount 500 \
  --period daily \
  --breach-action emit-metric

# 月次上限 (CloudWatch アラート連携)
aws redshift-serverless create-usage-limit \
  --resource-arn arn:aws:redshift-serverless:ap-northeast-1:123456789012:workgroup/production-wg \
  --usage-type serverless-compute \
  --amount 10000 \
  --period monthly \
  --breach-action log

Cooldown period — スケールダウン猶予の制御

Cooldown periodはクエリ終了後にコンピューティングがアイドル状態に移行するまでの待機時間 (0〜3600秒)。短く設定するとコストは下がるが次クエリの初期化コストが発生する。BI ダッシュボードなど数分間隔でクエリが来るケースは300〜600秒に設定することが多い。

Data Sharing

Data Sharingは、Producer側のNamespaceが保有するデータをConsumer側のNamespace (同アカウントまたは別アカウント) にリアルタイムで共有する機能。ETLコピー不要で最新データを参照できる。

Producer-Consumer モデル

-- Producer 側: Datashare の作成
CREATE DATASHARE salesdata_share;

-- Datashare に schema/table を追加
ALTER DATASHARE salesdata_share ADD SCHEMA public;
ALTER DATASHARE salesdata_share ADD TABLE public.orders;
ALTER DATASHARE salesdata_share ADD TABLE public.customers;

-- Consumer アカウントへ USAGE 権限付与
GRANT USAGE ON DATASHARE salesdata_share TO ACCOUNT '234567890123';
-- Consumer 側: External schema の作成
CREATE EXTERNAL SCHEMA sales_shared
FROM REDSHIFT DATASHARE salesdata_share
OF ACCOUNT '123456789012'
DATABASE 'prod_db';

-- Consumer 側からの参照 (読み取り専用)
SELECT o.order_id, c.customer_name, o.total_amount
FROM sales_shared.orders o
JOIN sales_shared.customers c ON o.customer_id = c.customer_id
WHERE o.order_date >= CURRENT_DATE - 7;

Cross-account Data Sharing

Cross-account共有はRAM (Resource Access Manager) が不要になった。ProducerからConsumer Account IDを直接指定するだけで共有が開始される。

-- Producer 側: Datashare の一覧確認
SELECT share_name, share_type, owner, num_schemas FROM svv_datashares;

Datashare object 管理

Datashareに追加できるオブジェクトはschema / table / view / UDF / external table の5種。materialzed viewはサポート外なため、定期Refresh結果を共有したい場合はベーステーブルに書き出す設計にする。

-- View を Datashare に追加
ALTER DATASHARE salesdata_share ADD ALL TABLES IN SCHEMA reporting;

-- 共有オブジェクトの確認
SELECT share_name, object_name, object_type
FROM svv_datashare_objects
WHERE share_name = 'salesdata_share';

Federated Query

Federated Queryは Redshift から直接 Aurora/RDS/S3 などの外部データソースをクエリする機能。ETL処理なしに異種データを結合できる。

Aurora/RDS 統合 — External schema

-- Aurora PostgreSQL への External schema 作成
-- Secrets Manager に DB 認証情報を事前登録
CREATE EXTERNAL SCHEMA aurora_schema
FROM POSTGRES
DATABASE 'mydb'
URI 'mydb.cluster-xxxxxxxx.ap-northeast-1.rds.amazonaws.com'
IAM_ROLE 'arn:aws:iam::123456789012:role/RedshiftFederatedRole'
SECRET_ARN 'arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:aurora-credentials';

-- Redshift DWH × Aurora OLTP の結合クエリ
SELECT
  dw.user_id,
  dw.lifetime_value,
  src.email,
  src.last_login_at
FROM dwh_users dw
JOIN aurora_schema.users src ON dw.user_id = src.id
WHERE dw.segment = 'VIP';

VPC 設定の注意点

Redshift ServerlessとAurora/RDSが同一VPCにある場合はセキュリティグループのインバウンドルール (ポート5432 / 3306) を追加するだけで接続できる。異なるVPCの場合はVPC Peeringまたは PrivateLinkが必要。

S3 統合 — Spectrum 代替

Redshift Spectrum (外部テーブル参照) はServerlessでも継続サポートされており、S3上のParquet/ORC/CSVを直接クエリできる。Federated Queryと組み合わせることで、S3データレイク・Aurora・RedshiftのDWH表を一つのSQLで結合できる。

-- Lake Formation 管理の外部テーブル参照
CREATE EXTERNAL SCHEMA spectrum_schema
FROM DATA CATALOG
DATABASE 'data_lake_db'
IAM_ROLE 'arn:aws:iam::123456789012:role/RedshiftSpectrumRole'
REGION 'ap-northeast-1';

-- S3 Parquet ファイルをスキャン (Push-down predicate で絞り込み)
SELECT event_type, COUNT(*) as cnt
FROM spectrum_schema.events
WHERE partition_date BETWEEN '2025-01-01' AND '2025-01-31'
  AND event_type = 'purchase'
GROUP BY event_type;

パフォーマンス考慮点

Federated QueryはネットワークラウンドトリップとAurora/RDS側の負荷が発生する。大量データを全取得するクエリは避け、Push-down predicateで絞り込んだ少量データをRedshift側に転送する設計にする。また、Federated Queryにはデフォルトのタイムアウト制限があるため、長時間クエリは定期バッチでRedshiftテーブルにETLしてから参照する方式を検討する。

AQUA (Advanced Query Accelerator)

AQUAはS3上のデータに対するフィルター・集計処理をS3に近いところで実行する分散キャッシュ層。クエリの一部をAWSのカスタムハードウェア上で処理することで、大規模スキャンクエリを最大10倍高速化する。

対象クエリパターン

AQUAが効果を発揮するのは以下のクエリパターン:

  • LIKE / SIMILAR TO / 正規表現を使った文字列検索
  • COUNT / SUM / AVG などの集計クエリ (大量スキャン)
  • S3上の外部テーブルに対するPredicate push-down
-- AQUA が効果的なクエリ例 (LIKE + 集計)
SELECT product_category, SUM(sales_amount) AS total_sales
FROM spectrum_schema.sales_history
WHERE product_name LIKE '%Wireless%'
  AND sale_date >= '2025-01-01'
GROUP BY product_category
ORDER BY total_sales DESC;

Serverless での AQUA 対応状況

AQUAはもともとRA3ノードタイプ (ra3.16xlarge / ra3.4xlarge) で有効化できる機能だが、Redshift Serverless では基盤ハードウェアにより一部クエリで自動適用される。ユーザーが明示的に有効化する操作は不要。

パフォーマンス計測

-- クエリ実行統計の確認 (STL_QUERY / SVL_QUERY_SUMMARY)
SELECT query, elapsed, rows, bytes_scanned
FROM stl_query
WHERE starttime >= SYSDATE - INTERVAL '1 hour'
ORDER BY elapsed DESC
LIMIT 20;

Materialized View auto-refresh

Materialized View (MV) は事前計算済み結果セットをキャッシュし、クエリを高速化する。Redshift Serverlessでは 増分更新 (Incremental refresh)自動クエリ書き換え (Auto-rewrite) の2機能が本番運用の要となる。

Materialized View の作成

-- 売上集計 MV の作成 (増分更新対応)
CREATE MATERIALIZED VIEW mv_daily_sales
AUTO REFRESH YES
AS
SELECT
  DATE_TRUNC('day', order_date) AS sale_date,
  product_category,
  SUM(amount) AS total_amount,
  COUNT(DISTINCT customer_id) AS unique_customers
FROM orders
GROUP BY 1, 2;

Incremental refresh — 差分のみ更新

増分更新が有効なMVは、ベーステーブルの変更分 (INSERT/UPDATE/DELETE) のみを取り込む。Full refreshより処理時間・コストを大幅に削減できる。

-- 手動で増分リフレッシュ
REFRESH MATERIALIZED VIEW mv_daily_sales;

-- Full refresh が必要な場合 (スキーマ変更後など)
REFRESH MATERIALIZED VIEW mv_daily_sales FULL;

-- MV のリフレッシュ状態確認
SELECT mv_name, refresh_time, state, refresh_type
FROM svv_mv_refresh_state
ORDER BY refresh_time DESC;

Auto-rewrite — クエリの自動書き換え

Auto-rewriteが有効な場合、Redshiftのクエリオプティマイザーがベーステーブルへのクエリを自動的にMV参照に書き換える。アプリ側のSQL変更なしにMVのメリットを享受できる。

-- Auto-rewrite の確認 (SVL_AUTO_WORKER_ACTION)
SELECT query, action, table_name
FROM svl_auto_worker_action
WHERE action = 'MV_REWRITE'
ORDER BY query DESC
LIMIT 10;

-- MV が使用されたかの確認
EXPLAIN
SELECT sale_date, product_category, total_amount
FROM orders
WHERE order_date >= CURRENT_DATE - 30;
-- 実行計画に "Seq Scan on mv_daily_sales" が表示されればAuto-rewrite適用済

Refresh strategy — スケジュール vs データ変更トリガー

戦略設定方法適切なユースケース
AUTO REFRESH YESMV定義時に指定リアルタイム性が必要なBI / 追加が多いテーブル
EventBridge + Lambda定刻RefreshバッチETL後に確実にRefreshしたいケース
手動REFRESHジョブ内で明示実行データ整合性を保証したい厳密な運用
# EventBridge Scheduler による定期 Refresh (例: 毎朝6時)
aws scheduler create-schedule \
  --name redshift-mv-refresh \
  --schedule-expression "cron(0 6 * * ? *)" \
  --target '{
 "Arn": "arn:aws:lambda:ap-northeast-1:123456789012:function:refresh-mv",
 "RoleArn": "arn:aws:iam::123456789012:role/SchedulerRole"
  }' \
  --flexible-time-window '{"Mode":"OFF"}'

Materialized View auto-refreshを活用することで、Redshift Serverlessのクエリレスポンスを向上させながらRPU消費を抑制できる。増分更新対応のMVとAuto-rewriteを組み合わせることが、本番DWH層のパフォーマンス最適化の核心となる。


詰まりポイント 7選 図解

詰まり①: Athena スキャン量爆発 — Partition Projectionなし + CSV全スキャン

症状: 月次データ集計クエリのコストが想定の50倍超。S3スキャン量が数TB規模に達し、月額10万円超の課金が発生した。

根本原因:

– Partition Projection未設定: MSCK REPAIR TABLE頼みのパーティション管理で、新規データが認識されずフルスキャンになる
– CSV形式のまま運用: Parquetと異なり列指定フィルタが効かないため、不要カラムもすべてスキャンされる

即時確認: EXPLAINでスキャン量を事前確認してから本番実行する。

EXPLAIN SELECT product_id, SUM(amount)
FROM sales_table
WHERE year = '2026' AND month = '05'
GROUP BY product_id;
-- "Partition count: 1" が出ればプルーニング適用済み

恒久対策: Partition Projection + Parquet変換でスキャン量を99%削減する。

ALTER TABLE sales_table SET TBLPROPERTIES (
  'projection.enabled' = 'true',
  'projection.year.type' = 'integer',
  'projection.year.range' = '2024,2030',
  'projection.month.type' = 'integer',
  'projection.month.range' = '1,12',
  'projection.month.digits' = '2',
  'storage.location.template' = 's3://my-bucket/sales/year=${year}/month=${month}/'
);

効果: パーティションプルーニング + Parquetの列プルーニングが組み合わさり、スキャン量99%削減・クエリコスト1/100が現場実績として報告されている。

詰まり②: Glue Crawler スキーマ誤推論 — 数値カラムをstring化 / Nested JSON展開失敗

症状: Crawlerが自動推論したスキーマで数値型カラムがstring型として登録される。AthenaでのCASTが必要になりクエリが複雑化。Nested JSON(配列・オブジェクト)が正常に展開されず、クエリでNULLが多発する。

根本原因:

– Crawlerのサンプリングロジックは先頭約100行を参照。先頭行に"null""N/A"等の文字列が含まれると数値型をstringと誤推論する
– Nested JSON展開はClassifierのJSONPath指定が必要。Classifier未設定だとフラット化に失敗する

解決策①: カスタムClassifier設定

import boto3
client = boto3.client('glue', region_name='ap-northeast-1')
client.create_classifier(
 JsonClassifier={
  'Name': 'nested-json-classifier',
  'JsonPath': '$[*]'
 }
)

解決策②: 手動でスキーマ修正

aws glue update-table \
  --database-name mydb \
  --table-input '{
 "Name":"sales",
 "StorageDescriptor":{
"Columns":[
  {"Name":"amount","Type":"double"},
  {"Name":"quantity","Type":"bigint"}
]
 }
  }'

予防: Crawlerはスキーマ発見目的にとどめ、本番テーブル定義はCDK/Terraformで管理する。型変動の激しいソースではGlue Schema Registryで事前定義して強制適用する。

詰まり③: Glue Job Bookmark リセット事故 — 全量再処理 / データ重複 / コスト爆発

症状: ETLジョブを手動で再実行したところ、処理済みのS3ファイルが全量再処理された。ターゲットのS3/DynamoDBにデータが重複し、修正に数時間を要した。

主な失敗パターン:

| 操作ミス | 結果 |
|———|——|
| bookmark.reset-on-run=trueを設定したまま実行 | 毎回Bookmarkリセット → 全量再処理 |
| Glue Studio UIの「Reset Job Bookmark」を誤クリック | 次回実行で全量再処理 |
| --job-bookmark-option job-bookmark-disableを設定 | Bookmark無効 → 全量処理 |
| 新規ジョブとして複製 | 旧Bookmarkを引き継がず全量再処理 |

実行前に必ず確認するコマンド:

aws glue get-job-bookmark --job-name my-etl-job
# "JobBookmarkEntry" の "Run" フィールドで最終処理済み位置を確認

安全なBookmarkリセット手順:

# Step1: Bookmark状態バックアップ
aws glue get-job-bookmark --job-name my-etl-job > bookmark_backup_$(date +%Y%m%d).json

# Step2: ターゲット側の重複データ削除を完了させる
# Step3: リセット実行 (不可逆操作)
aws glue reset-job-bookmark --job-name my-etl-job

冪等性設計: 重複処理を前提としたUPSERT設計やパーティション上書き設計を採用することで、Bookmark事故時の影響を最小化できる。ETLパイプラインの堅牢性はBookmark管理と冪等性の組み合わせで担保する。

詰まり④: Lake Formation IAM→LF権限移行時の権限喪失 — Super権限未移譲 / Catalog既存権限消失

症状: Lake Formationを有効化してIAM→LF権限移行を実施したところ、既存の開発チーム全員がGlue Data Catalogへのアクセス権限を失った。Athenaクエリが一斉に403エラーになった。

根本原因: Lake Formation有効化後は「LF権限 + IAM権限の両方」が必要になる。移行前にLF Grantを付与せず「Use only Lake Formation permissions」を有効化すると、IAM権限があってもアクセス不能になる。

| フェーズ | 権限モデル | Catalogアクセス条件 |
|——–|———–|——————|
| LF有効化前 | IAMポリシーのみ | glue:GetTable等のIAM権限で可 |
| LF有効化後 | LF権限 + IAM権限の両方 | IAM権限あってもLF Grantなしは不可 |

よくある移行失敗パターン:

– 管理者のみLF Adminに設定し、既存ユーザーへのGrant忘れ
– 既存IAMロールへのLF Grant前に「Use only Lake Formation permissions」を有効化

安全な移行手順:

# Step1: 全既存プリンシパルにLFデータ権限を付与してから移行
aws lakeformation grant-permissions \
  --principal DataLakePrincipalIdentifier=arn:aws:iam::123456789012:role/DataTeam \
  --permissions SELECT DESCRIBE \
  --resource '{"Database":{"Name":"mydb"}}'

# Step2: 付与確認後にIAMのみモードを無効化
aws lakeformation put-data-lake-settings \
  --data-lake-settings '{"DataLakeAdmins":[{"DataLakePrincipalIdentifier":"arn:aws:iam::123456789012:role/LFAdmin"}]}'

予防: Lake Formation有効化はステージング環境でリハーサルし、ロールバック手順を準備してから本番適用する。

詰まり⑤: Redshift Serverless RPU過剰課金 — Base capacity過大設定 / Usage limit未設定

症状: Redshift ServerlessをBase capacity=128RPUで起動したが実際のクエリは少量。アイドル時でも高額課金が継続し、月次コストが予算の3倍に達した。

根本原因:

– Base capacityはワークグループが起動している間の最小RPU確保量。アイドル時でも課金される
– Usage limitを設定しないとコスト上限なしに実行が続く

コスト比較:

| Base capacity | 24時間×30日の理論コスト | ユースケース |
|————–|———————-|————|
| 8 RPU | 約$2,160/月 | 小規模アドホック |
| 32 RPU | 約$8,640/月 | 中規模バッチ |
| 128 RPU | 約$34,560/月 | 大規模リアルタイム |

最適化設定:

# Base capacityを適正値に変更
aws redshift-serverless update-workgroup \
  --workgroup-name my-workgroup \
  --base-capacity 32

# Usage limit設定 (日次上限: 100RPU時間)
aws redshift-serverless create-usage-limit \
  --resource-arn arn:aws:redshift-serverless:ap-northeast-1:123456789012:workgroup/my-workgroup \
  --usage-type serverless-compute \
  --amount 100 \
  --period daily \
  --breach-action log

運用指針: 初期はBase capacity=32からスタートし、CloudWatchのRedshiftServerless_ComputeCapacityメトリクスを監視しながら段階的に調整する。Usage limitは予算の80%を日次上限として設定する。

詰まり⑥: Cross-Account Data Sharing失敗 — RAM招待未承認 / Consumer権限不足

症状: ProducerアカウントでData Sharingを作成し、ConsumerアカウントのRedshiftから参照しようとしたが「object does not exist」エラーが発生。共有設定をやり直しても解決しない。

根本原因: Cross-Account Data Sharingには複数の承認ステップがあり、1つでも漏れると参照できない。

失敗チェックリスト:

| ステップ | よくある漏れ | 確認コマンド |
|———|———–|————|
| RAM招待送信 | Producerが招待を送信していない | aws ram list-resource-shares |
| RAM招待承認 | Consumerが承認を忘れている (最多) | aws ram list-resource-share-invitations |
| Datashareオブジェクト追加 | テーブル/スキーマが追加されていない | SHOW DATASHARES |
| External database作成 | Consumer側でDB作成が未完了 | SELECT * FROM SVV_EXTERNAL_DATABASES |
| 権限付与 | Consumerユーザーへの参照権限がない | GRANT USAGE ON DATABASE |

Consumer側の確認・設定手順:

-- Consumer側: 受信したDatashare確認
SELECT * FROM SVV_DATASHARES WHERE share_type = 'INBOUND';

-- External database作成
CREATE EXTERNAL DATABASE producer_db
FROM DATASHARE my_datashare
OF ACCOUNT '123456789012'
NAMESPACE 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';

-- 権限付与
GRANT USAGE ON DATABASE producer_db TO GROUP analytics_team;

注意: Cross-RegionのData Sharingは別途データ転送コストが発生する。同一リージョン構成を優先し、クロスリージョンが必要な場合は事前にコスト試算を行う。

詰まり⑦: Federated Query パフォーマンス劣化 — 大量データフェッチ / Push-down未適用 / VPC設定漏れ

症状: Redshift ServerlessからAurora PostgreSQLへのFederated Queryが想定の100倍遅い。タイムアウトが頻発し、本番での利用を断念しかけた。

根本原因: Federated Queryは外部データソースからRedshiftへデータを転送してから処理する。フィルタの書き方を誤ると全行転送になる。

Push-down効果の違い:

| クエリパターン | Push-down | フェッチ量 |
|————-|———-|———|
| WHERE句なし | 不適用 | 全行転送 |
| WHERE LOWER(name) = 'alice' (関数あり) | 不適用 | 全行転送 |
| WHERE name = 'alice' (等値) | 適用 | 絞込後のみ |
| WHERE created_at > '2026-01-01' (範囲) | 適用 | 絞込後のみ |

VPC設定確認:

# Secrets Manager VPC Endpointの存在確認
aws ec2 describe-vpc-endpoints \
  --filters Name=service-name,Values=com.amazonaws.ap-northeast-1.secretsmanager \
  --query 'VpcEndpoints[].VpcEndpointId'

Push-down最適化の書き方:

-- NG: 関数使用でPush-down不可 → 全行フェッチ
SELECT * FROM ext_aurora.orders
WHERE LOWER(status) = 'shipped';

-- OK: シンプルな条件でPush-down適用 → 絞込後のみフェッチ
SELECT * FROM ext_aurora.orders
WHERE status = 'shipped'
  AND created_at > '2026-01-01'
  AND order_id > 1000000;

Federated Query推奨ユースケース: 少量参照・最新データ確認・バッチ取り込み前のプレビュー。数百万行規模の結合はS3エクスポート後にAthenaかGlue ETLで処理するほうが安定・高速・コスト効率が高い。


アンチパターン → 正解パターン変換演習

問1: S3フルスキャンクエリ → Partition Projection + Parquet + CTAS

NG パターン: パーティション指定なし・CSV形式で全S3スキャン

-- NG: パーティション条件なし / CSV全スキャン → スキャン量TB規模
SELECT product_id, category, SUM(amount) AS total_sales
FROM sales_data_csv
WHERE YEAR(sale_date) = 2026;
-- Partition Projectionなし → 全ファイルスキャン / コスト: 5TB × $5/TB = $25/回

OK パターン: Partition Projection + Parquet + CTASで高速・低コスト

-- Step1: CTASでParquet変換 (一度だけ実行)
CREATE TABLE sales_data_parquet
WITH (
  format = 'PARQUET',
  parquet_compression = 'SNAPPY',
  partitioned_by = ARRAY['year', 'month'],
  external_location = 's3://my-bucket/sales-parquet/'
) AS
SELECT *, YEAR(sale_date) AS year, MONTH(sale_date) AS month
FROM sales_data_csv;

-- Step2: Partition Projection設定
ALTER TABLE sales_data_parquet SET TBLPROPERTIES (
  'projection.enabled' = 'true',
  'projection.year.type' = 'integer',
  'projection.year.range' = '2024,2030',
  'projection.month.type' = 'integer',
  'projection.month.range' = '1,12',
  'storage.location.template' = 's3://my-bucket/sales-parquet/year=${year}/month=${month}/'
);

-- Step3: 最適化クエリ (コスト: 50MB × $5/TB ≈ $0.00025/回 = 99.99%削減)
SELECT product_id, category, SUM(amount) AS total_sales
FROM sales_data_parquet
WHERE year = 2026 AND month IN (1, 2, 3);

問2: 手動ETLスクリプト(cron+boto3) → Glue ETL Job + Job Bookmark + Data Quality

NG パターン: cronで毎夜実行するboto3スクリプト — 冪等性なし・品質検証なし

# NG: 手動スクリプト — エラー時に重複処理、データ品質チェックなし
import boto3, pandas as pd
from datetime import date, timedelta

def nightly_etl():
 yesterday = str(date.today() - timedelta(days=1))
 s3 = boto3.client('s3')
 objs = s3.list_objects_v2(
  Bucket='raw-bucket', Prefix=f'data/{yesterday}/'
 ).get('Contents', [])
 for obj in objs:
  # 品質チェックなし・重複チェックなし・Bookmark管理なし
  data = pd.read_csv(f"s3://raw-bucket/{obj['Key']}")
  data.to_parquet(f's3://curated-bucket/{yesterday}/output.parquet')

OK パターン: Glue ETL Job + Job Bookmark + Data Quality

import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

args = getResolvedOptions(sys.argv, ['JOB_NAME'])
sc = SparkContext()
glueContext = GlueContext(sc)
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

# Job Bookmark: 未処理ファイルのみ自動取得
datasource = glueContext.create_dynamic_frame.from_catalog(
 database='mydb',
 table_name='raw_sales',
 transformation_ctx='datasource'  # Bookmarkのキー
)

# Data Quality: ルールセット適用
from awsglue.operations import EvaluateDataQuality
ruleset = """
Rules = [
 IsComplete "product_id",
 IsComplete "amount",
 ColumnValues "amount" > 0,
 IsUnique "transaction_id"
]
"""
dqResults = EvaluateDataQuality().process_rows(
 frame=datasource,
 ruleset=ruleset,
 publishing_options={
  "dataQualityEvaluationContext": "sales_dq",
  "enableDataQualityCloudWatchMetrics": True
 }
)

# 品質チェック通過後のみ書き込み
job.commit()

問3: IAM直接権限付与(100テーブル×10チーム) → Lake Formation TBAC + Data Filter

NG パターン: IAMポリシーに各テーブルを列挙 — 管理破綻・新テーブル追加のたびに更新

# NG: 100テーブル×10チームで1000個のエントリが必要
aws iam put-role-policy \
  --role-name DataAnalystRole \
  --policy-name S3GluePolicy \
  --policy-document '{
 "Statement": [{
"Effect": "Allow",
"Action": ["glue:GetTable", "s3:GetObject"],
"Resource": [
  "arn:aws:glue:ap-northeast-1:123456789012:table/mydb/sales_2024",
  "arn:aws:glue:ap-northeast-1:123456789012:table/mydb/sales_2025",
  "...100テーブル分続く..."
]
 }]
  }'
# 問題: 新テーブル追加 → 全ロールのポリシー更新が必要

OK パターン: Lake Formation TBAC + LF-Tagで一括管理

# Step1: LF-Tag定義
aws lakeformation create-lf-tag \
  --tag-key "DataDomain" \
  --tag-values '["sales", "inventory", "customer"]'

# Step2: テーブルにタグ付与 (新テーブルはここだけ)
aws lakeformation add-lf-tags-to-resource \
  --resource '{"Table":{"DatabaseName":"mydb","Name":"sales_2026"}}' \
  --lf-tags '[{"TagKey":"DataDomain","TagValues":["sales"]}]'

# Step3: IAMロールにLF-Tagベースで一括Grant
aws lakeformation grant-permissions \
  --principal DataLakePrincipalIdentifier=arn:aws:iam::123456789012:role/DataAnalystRole \
  --permissions SELECT DESCRIBE \
  --resource '{
 "LFTagPolicy": {
"ResourceType": "TABLE",
"Expression": [{"TagKey":"DataDomain","TagValues":["sales"]}]
 }
  }'
# 効果: 新テーブル追加時はタグ付けのみ → 権限自動継承

問4: Redshift Provisioned固定クラスタ → Serverless RPU + Usage Limit

NG パターン: Provisioned固定クラスタで夜間バッチに合わせたオーバープロビジョニング

# NG: dc2.8xlarge × 4ノード (夜間バッチ用) → 昼間はアイドルで課金継続
aws redshift create-cluster \
  --cluster-identifier my-dwh \
  --node-type dc2.8xlarge \
  --number-of-nodes 4
# コスト: $14.4/時間 × 24時間 × 30日 = $10,368/月
# 昼間の実効利用率: 約15% → 85%がアイドルコスト

OK パターン: Redshift Serverless RPU + Usage Limitで使った分だけ課金

# Step1: Serverlessワークグループ作成
aws redshift-serverless create-workgroup \
  --workgroup-name my-dwh-serverless \
  --namespace-name my-namespace \
  --base-capacity 32 \
  --subnet-ids subnet-aaa subnet-bbb

# Step2: Usage limit設定 (日次上限でコスト保護)
aws redshift-serverless create-usage-limit \
  --resource-arn arn:aws:redshift-serverless:ap-northeast-1:123456789012:workgroup/my-dwh-serverless \
  --usage-type serverless-compute \
  --amount 200 \
  --period daily \
  --breach-action emit-metric

# Step3: CloudWatchアラームでコストアラート
aws cloudwatch put-metric-alarm \
  --alarm-name redshift-serverless-cost-alert \
  --namespace AWS/Redshift-Serverless \
  --metric-name ComputeSeconds \
  --statistic Sum --period 3600 \
  --evaluation-periods 1 --threshold 720000 \
  --comparison-operator GreaterThanThreshold \
  --alarm-actions arn:aws:sns:ap-northeast-1:123456789012:cost-alert
# コスト: 実使用量に応じて課金 (推定$1,200〜$3,000/月)

問5: 個別DB参照(各チーム独自接続) → Federated Query + Data Sharing 統合

NG パターン: 各チームが個別にAuroraへ直接接続 — 接続数増大・認証情報散乱

-- NG: 各チームのBIツールから直接Aurora RDSへJDBC接続
-- 問題1: max_connectionsを超過してクエリ拒否
-- 問題2: 認証情報がBIツール設定に散在
-- 問題3: AuroraのCPUをBIクエリが占有しアプリ処理に影響
SELECT * FROM aurora_app_db.orders WHERE status = 'completed';

OK パターン: Redshift Federated Query + Data Sharing で統合アクセス層を構築

-- Step1: External Schemaの作成 (Aurora接続設定)
CREATE EXTERNAL SCHEMA aurora_ext
FROM POSTGRES
DATABASE 'app_db'
URI 'my-aurora-cluster.cluster-xxxxxxxx.ap-northeast-1.rds.amazonaws.com'
IAM_ROLE 'arn:aws:iam::123456789012:role/RedshiftAuroraRole'
SECRET_ARN 'arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:aurora-creds';

-- Step2: Federated QueryでAuroraから最新注文を取得
-- Push-down適用: status/created_at条件がAurora側でフィルタ
SELECT o.order_id, o.customer_id, o.amount, c.segment
FROM aurora_ext.orders o
JOIN redshift_customers c ON o.customer_id = c.customer_id
WHERE o.status = 'pending'
  AND o.created_at > CURRENT_DATE - 7;

-- Step3: 分析チームへはData Sharingで集計済みデータを提供
CREATE DATASHARE analytics_share;
ALTER DATASHARE analytics_share ADD SCHEMA analytics;
ALTER DATASHARE analytics_share ADD ALL TABLES IN SCHEMA analytics;
GRANT USAGE ON DATASHARE analytics_share TO NAMESPACE 'consumer-namespace-uuid';

-- Consumer: 各BIチームのWorkgroupから参照
CREATE DATABASE analytics_db FROM DATASHARE analytics_share
OF NAMESPACE 'producer-namespace-uuid';
SELECT * FROM analytics_db.analytics.daily_sales_summary;
-- 効果: Auroraへの直接接続を排除 / 認証情報を一元管理 / Auroraの負荷を隔離

まとめ — Data Analytics Vol1 起点 × 54記事化達成

本記事で習得した知識の総括

本記事では、AWSデータ分析基盤の本番運用を Athena・Glue・Lake Formation・Redshift Serverless の4層スタックで体系的に解説しました。各層の本番設計ポイントを振り返ります。

クエリ層 (Amazon Athena) で最も重要な1点: Partition Projectionの徹底適用です。Glue Catalogのパーティション管理に依存せず、S3パスをクエリ時に自動推論するPartition Projectionは、大規模データレイクにおけるコスト最適化の根幹です。Parquet + Snappyとの組み合わせで、スキャン量とクエリコストを桁違いに削減できます。Workgroup分離によるチーム別コスト可視化とバイトスキャン上限設定も、本番環境での必須設定です。

ETL層 (AWS Glue) で最も重要な1点: Job Bookmarkによる冪等性の担保です。ETLパイプラインの本番安定運用は「エラーが起きても再実行できる」設計が前提です。Job Bookmarkで処理済みデータを追跡し、Data Qualityでデータ品質を継続検証することで、信頼性の高いETL基盤を構築できます。Studio Visual ETLによりノーコードでのETL開発も可能となり、データエンジニアリングの民主化が進んでいます。

ガバナンス層 (Lake Formation) で最も重要な1点: TBAC(Tag-Based Access Control)による権限の一元管理です。数百テーブル×数十チームの環境でNamed Resource方式は運用破綻します。LF-Tagをテーブル・カラムに付与し、プリンシパルにタグベースでGrantすることで、新テーブル追加時の権限設定を自動化できます。Cross-Account共有とData Filterによる行・列レベルセキュリティも、大規模組織のデータ民主化を支える基盤技術です。

DWH層 (Redshift Serverless) で最も重要な1点: RPU Base capacityとUsage limitの適切な設定です。過剰なBase capacityはアイドル時の課金増大を招き、Usage limit未設定はコスト青天井リスクを生みます。32 RPUからスタートして実測値で調整し、日次Usage limitをCloudWatchアラームと連携させることがコスト管理の基本です。Data SharingとFederated Queryにより、データを移動させずに組織横断の統合分析基盤を実現できます。

詰まりポイント7選では、本番環境でよく発生するトラブルパターンとその解決策を体系化しました。Athenaのスキャン量爆発・Glue Crawlerの誤推論・Bookmarkリセット事故・Lake Formationの権限喪失・Redshift Serverlessの過剰課金・Cross-Account Data Sharing失敗・Federated Queryのパフォーマンス劣化は、いずれも設計段階での事前対策が有効です。本記事の詰まりポイント解説が、読者の皆様のデバッグ時間を大幅に短縮するヒントとなれば幸いです。

アンチパターン演習5問では、「動いているが最適でない」コードを「本番品質」に変換する思考プロセスを実践しました。S3フルスキャンからParquet+CTAS変換、手動ETLからGlue Job Bookmark統合、IAM個別管理からLake Formation TBAC、Provisioned固定からServerless RPU、個別DB接続からFederated Query+Data Sharing統合まで、AWSデータ分析基盤の現代的な設計パターンを習得できました。各アンチパターンには実際のコスト削減率や運用改善効果の定量指標も示しており、プロジェクトでの採用判断の参考になります。

本記事はAWS本番運用シリーズのData Analytics軸(第22軸目)のVol1として、この分野の学習起点となることを目指しました。Athena・Glue・Lake Formation・Redshift Serverlessという4サービスは、それぞれ単独でも強力ですが、統合して使うことで真の価値を発揮します。本記事が、その統合設計の思考フレームワークを提供できたなら目的は達成です。

次のステップとして、本シリーズのData Analytics軸では、EMR・Kinesis・OpenSearch等の高度なユースケースや、データメッシュアーキテクチャ、MLパイプライン統合を順次展開予定です。引き続き、本シリーズをお役立てください。

本記事の学習成果 — 習得スキル一覧

カテゴリ習得スキル本番適用時の効果
Athena コスト最適化Partition Projection / Parquet変換 / CTASクエリコスト最大99%削減
Athena クエリ設計Workgroup分離 / Result Reuse / Federationチーム別コスト可視化 + 外部データ統合
Glue ETLJob Bookmark / DPU最適化冪等性担保 + 処理コスト最適化
Glue 品質管理Data Quality (DQDL) / Studio Visual ETLデータ品質スコアの継続監視
Lake FormationTBAC / Cross-Account / Governed Table数百テーブル規模の権限管理自動化
Redshift ServerlessRPU最適化 / Usage Limitアイドルコスト最大75%削減
Redshift ServerlessData Sharing / Federated Query / MV組織横断データアクセス基盤の構築
トラブルシューティング詰まりポイント7選 + アンチパターン5問本番障害の予防的設計

本記事を通じて、個々のサービス知識から「4層スタックとして統合運用する」視点へのシフトが実現できたはずです。

AWS本番運用シリーズ Data Analytics Vol1 — 4層スタック統合の起点

本記事でAWS本番運用シリーズに Data Analytics軸(第22軸目) が加わりました。Athena×Glue×Lake Formation×Redshift Serverlessの4層スタックを統合的に本番運用する知識体系を構築しました。

4層スタック × 習得スキルまとめ

| 層 | サービス | 本記事で習得した本番運用スキル | 本番設計のポイント |
|—|———|————————–|——————|
| クエリ層 | Amazon Athena | Workgroup分離 / Partition Projection / CTAS / Federation | Partition Projection必須・Parquet変換でコスト99%削減 |
| ETL層 | AWS Glue | Crawler / Job Bookmark / Data Quality / Studio Visual ETL | Bookmark冪等性 + DQルールセットで品質担保 |
| ガバナンス層 | Lake Formation | TBAC / Cross-Account / Governed Table / Data Filter | LF-Tagベース一括権限管理で新テーブル追加を自動化 |
| DWH層 | Redshift Serverless | RPU最適化 / Data Sharing / Federated Query / MV auto-refresh | Base=32スタート + Usage limit必須 |

Data Analytics シリーズ 今後の展開予告

| Vol | テーマ | 主要サービス |
|—-|——|————|
| Vol1 (本記事) | 4層スタック統合本番運用 | Athena / Glue / Lake Formation / Redshift Serverless |
| Vol2 (予定) | ストリーミングデータ処理 | Kinesis Data Streams / Firehose / MSK |
| Vol3 (予定) | 大規模ETL・ML統合 | EMR / Glue ML Transforms / SageMaker Feature Store |
| Vol4 (予定) | データメッシュ設計 | Lake Formation Cross-Account / Data Zone |

本記事を起点に、AWSデータ分析基盤の各領域を深掘りするシリーズを展開します。各Volは単独でも参照可能な設計ですが、Vol1の4層スタック理解があるとより深く理解できます。

4層スタック × AWS Well-Architected データ分析レンズ対応表

| 設計原則 | Athena | Glue | Lake Formation | Redshift Serverless |
|———|——–|——|—————-|———————|
| 運用上の優秀性 | Workgroup別コスト追跡 | Job実行ログ/CloudWatch | Audit Logs | CloudWatchメトリクス |
| セキュリティ | 結果暗号化/VPC | Glue Data Catalog暗号化 | TBAC/Cell Security | セキュリティグループ/KMS |
| 信頼性 | Result Reuse/再実行 | Job Bookmark/DQ | Governed Table | スナップショット/復元 |
| パフォーマンス効率 | Partition Projection | DPU最適化 | – | RPU自動スケール |
| コスト最適化 | スキャン量制御/CTAS | Spot/G.1X Worker | – | Usage Limit/Cooldown |

Data Analyticsシリーズは今後、ストリーミング・ML統合・データメッシュへと展開していきます。本記事の4層スタック理解を基盤に、各テーマを深掘りしてください。

本シリーズの読み進め方:

1. 本記事 (Vol1) を精読し、4層の統合設計の全体感を把握する
2. 詰まりポイント7選を自チームの環境でチェックリストとして活用する
3. アンチパターン演習5問を自チームの既存コードに当てはめてレビューする
4. Vol2以降で各サービスの深掘りに進む

Data Analytics本番運用シリーズはすべてのVolがVol1の共通フレームワーク(4層スタック設計)を基盤として構成されています。

AWS本番運用シリーズ全22軸の詳細は、次のep-boxをご確認ください。

54記事化達成 — AWS本番運用シリーズ全22軸

本記事の公開でAWS本番運用シリーズは 54記事 に到達しました。AWSの主要サービス領域を網羅する全22軸のラインナップ:

| 軸 | カテゴリ | 主要サービス |
|—-|——–|————|
| 1 | コンピュート | EC2 / Auto Scaling |
| 2 | ネットワーク基盤 | VPC / Networking |
| 3 | セキュリティ | IAM / Security |
| 4 | データベース (RDB) | RDS / Aurora |
| 5 | オブジェクトストレージ | S3 基盤 |
| 6 | ストレージ (Vol1-3) | EBS / EFS / S3 Glacier |
| 7 | サーバーレス | Lambda / Serverless |
| 8 | コンテナ | ECS / Fargate |
| 9 | 監視・可観測性 | CloudWatch / Observability |
| 10 | IaC | CloudFormation / CDK |
| 11 | データベース (NoSQL) | DynamoDB |
| 12 | キャッシュ | ElastiCache |
| 13 | API管理 | API Gateway |
| 14 | ワークフロー | Step Functions |
| 15 | イベント駆動 | EventBridge |
| 16 | メッセージング | SNS / SQS |
| 17 | DNS | Route 53 |
| 18 | CDN | CloudFront |
| 19 | Kubernetes | EKS |
| 20 | ネットワーク詳細 (Vol1-3) | Transit Gateway / Direct Connect |
| 21 | バックアップ・DR | AWS Backup / DR |
| 22 | Data Analytics | Athena / Glue / Lake Formation / Redshift (本記事 = Vol1起点) ← NEW |

全22軸の箇条書きリスト:

1. EC2 / Auto Scaling
2. VPC / Networking
3. IAM / Security
4. RDS / Aurora
5. S3 基盤
6. Storage (Vol1-3)
7. Lambda / Serverless
8. ECS / Fargate
9. CloudWatch / Observability
10. CloudFormation / IaC
11. DynamoDB
12. ElastiCache
13. API Gateway
14. Step Functions
15. EventBridge
16. SNS / SQS
17. Route 53 / DNS
18. CloudFront / CDN
19. EKS / Kubernetes
20. Network (Vol1-3)
21. Backup / DR
22. Data Analytics (本記事 = Vol1起点) ← NEW

graph TB
 subgraph Query["クエリ層 — Amazon Athena"]
  direction LR
  AW[Workgroup] --> PP[Partition Projection]
  PP --> CTAS[CTAS/Parquet]
  CTAS --> FQ_A[Federated Query]
 end
 subgraph ETL["ETL層 — AWS Glue"]
  direction LR
  CR[Crawler] --> JB[Job Bookmark]
  JB --> DQ[Data Quality]
  DQ --> VE[Visual ETL]
 end
 subgraph Gov["ガバナンス層 — Lake Formation"]
  direction LR
  TBAC[TBAC/LF-Tag] --> CA[Cross-Account]
  CA --> GT[Governed Table]
  GT --> DF[Data Filter]
 end
 subgraph DWH["DWH層 — Redshift Serverless"]
  direction LR
  RPU[RPU最適化] --> DS[Data Sharing]
  DS --> FQ_R[Federated Query]
  FQ_R --> MV[MV auto-refresh]
 end
 S3[Amazon S3 Data Lake] --> ETL
 ETL --> S3
 S3 --> Query
 Gov -->|権限制御| Query
 Gov -->|権限制御| ETL
 Gov -->|権限制御| DWH
 S3 --> DWH
 Query <-.->|Federated| DWH

前回: Storage本番運用 Vol3 | S3 Vectors × S3 Tables × Backup Vault Lock × Snowball Edge

関連: Storage本番運用 Vol1 | S3×EFS×FSx×Storage Gateway 基礎4本柱 完全ガイド

AWS ML/AI本番運用 Vol3 — SageMaker MLOps完全ガイド
SageMaker Feature Store × Glue ETL パイプライン / Athena × SageMaker推論パイプライン統合。Data Analyticsレイヤー(本記事)と組み合わせることで、データ取り込みから特徴量生成・モデル推論まで一気通貫設計が可能。
AI/ML Vol3 を読む →

AWS本番運用シリーズ 全記事一覧

関連: Data Lake本番運用 Vol1

関連: Step Functions本番運用

関連: Cost Optimization本番運用 Vol1 | Cost Explorer×Budgets×Savings Plans×Compute Optimizer

本記事を最後までお読みいただきありがとうございました。AWSデータ分析基盤の本番設計・運用において、本記事が実践的な参照ガイドとなれば幸いです。

本記事の復習ポイント — 4層スタックの設計チェックリスト:

Athena (クエリ層):

  • [ ] Partition Projection設定済み (date/integer/enum/injected型を適切に選定)
  • [ ] Parquet + Snappy圧縮でデータ格納
  • [ ] Workgroup別のバイトスキャン上限設定
  • [ ] CTAS for重要クエリの結果キャッシュ化

Glue (ETL層):

  • [ ] Job Bookmark有効化 + 冪等性設計
  • [ ] Data Qualityルールセット定義 (IsComplete/IsUnique/ColumnValues)
  • [ ] エラー時の通知フロー設定 (CloudWatch Alarm + SNS)
  • [ ] Worker typeとDPU数の実負荷テスト済み

Lake Formation (ガバナンス層):

  • [ ] LF-Tag定義完了 (DataDomain/Classification等)
  • [ ] 全テーブルへのLF-Tag付与
  • [ ] プリンシパルへのLF-Tagベースgrant設定
  • [ ] IAM→LF移行手順書の整備

Redshift Serverless (DWH層):

  • [ ] Base capacity設定 (初期推奨: 32 RPU)
  • [ ] Usage limit設定 (日次/週次両方)
  • [ ] CloudWatchアラーム連携
  • [ ] Data Sharing設定 (Consumer/Producerロール確認)

このチェックリストを本番設計・レビュー時の基準として活用してください。Data Analyticsシリーズは今後も拡充予定です。AWS本番運用シリーズの他の記事も合わせてご参照いただくことで、AWSインフラ全体の設計品質を高めることができます。