Skip to content

課題18: EC企業のデータレイク構築

難易度: 🟡 中級


1. 分類情報

項目内容
難易度中級
カテゴリデータ基盤
処理タイプバッチ
使用IaCCloudFormation
想定所要時間5-6時間

2. 学習するAWSサービス

この演習では以下のAWSサービスを実践的に学習します。

コア技術スタック

サービス役割学習ポイント
Amazon S3データレイクストレージ3層アーキテクチャ、ライフサイクル管理
AWS GlueETL、データカタログクローラー、ETLジョブ、スキーマ管理
Amazon AthenaサーバーレスSQLパーティションプルーニング、コスト最適化
Amazon QuickSightBIダッシュボードSPICE、可視化

3. 最終構成図


4. シナリオ

企業プロファイル

項目内容
企業名〇〇株式会社
業種総合EC(家電・日用品・ファッション)
従業員数500名(データチーム10名)
月間購買件数100万件
SKU数10万点
月間PV5000万PV

現状の課題

〇〇株式会社は急成長する総合ECサイトを運営しています。
データ活用において以下の課題を抱えています:

1. データサイロ化
   - 購買データはRDS (MySQL)
   - アクセスログはElasticsearch
   - 商品データはDynamoDB
   - それぞれ別々に分析、統合できない

2. 分析の遅延
   - 月次レポート作成に3日かかる
   - アドホック分析の依頼対応に1週間
   - リアルタイムな意思決定ができない

3. コスト非効率
   - 分析用に本番DBのレプリカを使用
   - 高額なBIツールのライセンス費用
   - データエンジニアの工数が分析に消費

4. スケーラビリティの限界
   - データ量増加でクエリが遅くなっている
   - 過去データの保持コストが増大
   - 新しい分析要件への対応が困難

ビジネス目標

KPI現状目標
月次レポート作成時間3日自動化(0日)
アドホック分析対応1週間1時間以内(セルフサービス)
データ統合率0%(サイロ化)100%
過去データ保持期間1年5年以上
分析コスト月100万円月30万円

5. 達成目標

主要な学習成果

この課題を完了すると、以下ができるようになります:

1. S3ベースのデータレイク構築
   - Raw/Processed/Curatedの3層アーキテクチャ
   - パーティショニングによる効率化
   - ライフサイクル管理でコスト最適化

2. AWS Glueによるデータ統合
   - クローラーによるスキーマ自動検出
   - ETLジョブでのデータ変換
   - Data Catalogによるメタデータ管理

3. Amazon Athenaによるクエリ分析
   - サーバーレスでのSQLクエリ
   - パーティションプルーニング
   - クエリ結果のキャッシング

4. Amazon QuickSightによるBI
   - ダッシュボード作成
   - SPICE によるパフォーマンス最適化
   - セルフサービス分析の実現

合格基準

項目基準
データレイクS3に3層構造でデータが格納されていること
ETLGlueジョブで日次データ処理が自動化されていること
クエリAthenaで主要な分析クエリが実行できること
ダッシュボードQuickSightで売上ダッシュボードが作成されていること
コストスキャン量の最適化が実装されていること

6. 使用するAWSサービス

コア技術スタック

yaml
ストレージ:
  - Amazon S3: データレイクストレージ
  - S3 Glacier: 長期アーカイブ

データ処理:
  - AWS Glue: ETL、データカタログ
  - AWS Glue DataBrew: データ準備(ノーコード)
  - Amazon EMR: 大規模データ処理(オプション)

クエリエンジン:
  - Amazon Athena: サーバーレスSQL
  - Amazon Redshift Spectrum: DWH連携(オプション)

可視化:
  - Amazon QuickSight: BIダッシュボード

オーケストレーション:
  - AWS Step Functions: ワークフロー管理
  - Amazon EventBridge: スケジュール実行

セキュリティ:
  - AWS Lake Formation: データレイクガバナンス
  - AWS IAM: アクセス制御
  - AWS KMS: 暗号化

GCPとの比較

機能AWSGCP
オブジェクトストレージS3Cloud Storage
データカタログGlue Data CatalogData Catalog
ETLGlueDataflow / Dataproc
サーバーレスクエリAthenaBigQuery
BIQuickSightLooker

7. 前提条件

技術要件

bash
# 必要なCLIツール
aws --version          # 2.x
python --version       # 3.9+

# AWS設定
aws configure
export AWS_REGION=ap-northeast-1
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export DATALAKE_BUCKET=company-datalake-${AWS_ACCOUNT_ID}

事前準備

bash
# サンプルデータの概要
# 以下のデータソースを想定:

1. 購買データ (orders.csv)
   - order_id, customer_id, order_date, total_amount, status

2. 注文明細 (order_items.csv)
   - order_item_id, order_id, product_id, quantity, unit_price

3. 商品マスタ (products.csv)
   - product_id, product_name, category, subcategory, brand, price

4. 顧客データ (customers.csv)
   - customer_id, name, email, prefecture, city, registration_date

5. アクセスログ (access_logs.json)
   - timestamp, user_id, page_url, action, device, session_id

7. トラブルシューティング課題

Challenge 1: Athenaクエリが遅い

問題:
カテゴリ別売上クエリの実行に5分以上かかる。
データスキャン量も10GB以上になっている。

クエリ:
SELECT category, SUM(total_amount)
FROM company_processed.orders o
JOIN company_processed.order_items oi ON o.order_id = oi.order_id
JOIN company_processed.products p ON oi.product_id = p.product_id
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31'
GROUP BY category

調査項目:
1. パーティションの活用状況
2. ファイルフォーマットとサイズ
3. JOIN最適化
解決のヒント
sql
-- 1. パーティションフィルタを使用
SELECT category, SUM(total_amount)
FROM company_processed.orders o
JOIN company_processed.order_items oi ON o.order_id = oi.order_id
JOIN company_processed.products p ON oi.product_id = p.product_id
WHERE o.year = 2024 AND o.month = 1  -- パーティションキーを使用
GROUP BY category;

-- 2. EXPLAIN で実行計画確認
EXPLAIN
SELECT category, SUM(total_amount)
FROM company_processed.orders ...;

-- 3. パーティション状態確認
SHOW PARTITIONS company_processed.orders;

-- 4. テーブル統計情報更新
ANALYZE TABLE company_processed.orders COMPUTE STATISTICS;

-- 5. Curatedゾーンの事前集計テーブルを使用
-- 日次バッチで集計済みデータを参照
SELECT category, SUM(total_sales)
FROM company_curated.daily_sales
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31'
GROUP BY category;

-- パフォーマンス比較:
-- Before: スキャン10GB、5分
-- After: スキャン100MB、5秒

Challenge 2: Glue ETLジョブがOOM(メモリ不足)で失敗

問題:
日次ETLジョブが大量データ処理時にメモリ不足で失敗する。

エラーログ:
Container killed by YARN for exceeding memory limits.
10.0 GB of 10 GB physical memory used.

データ量:
- 入力: 500万レコード
- 処理後: 1億レコード(JOIN後)

調査項目:
1. Spark設定
2. データ処理パターン
3. ワーカー設定
解決のヒント
python
# 1. ブロードキャスト結合の活用(小さいテーブル)
from pyspark.sql.functions import broadcast

# 商品マスタは小さいのでブロードキャスト
orders_with_products = orders_df.join(
    broadcast(products_df),  # 小さいテーブルをブロードキャスト
    'product_id'
)

# 2. データのパーティショニング
orders_df = orders_df.repartition(100, 'order_date')

# 3. キャッシュの適切な使用
products_df.cache()  # 複数回使うテーブルのみキャッシュ

# 4. 不要なカラムを早期に除外
orders_df = orders_df.select('order_id', 'customer_id', 'order_date', 'total_amount')

# 5. Glueジョブ設定の調整
# --conf spark.sql.shuffle.partitions=200
# --conf spark.sql.autoBroadcastJoinThreshold=52428800

# 6. ワーカー数とタイプの変更
aws glue update-job \
    --job-name company-orders-etl \
    --job-update '{
        "NumberOfWorkers": 10,
        "WorkerType": "G.2X"
    }'

Challenge 3: QuickSight SPICEデータセットの更新エラー

問題:
SPICEへのデータインポートが失敗する。
QuickSightダッシュボードが古いデータのまま。

エラー:
SPICE ingestion failed: Source data exceeds SPICE limits

状況:
- データセットサイズ: 50GB
- SPICE容量: 10GB
- 更新頻度: 日次

調査項目:
1. SPICEの制限
2. データ量の最適化
3. 代替アプローチ
解決のヒント
sql
-- 1. データ量を削減(直近データのみ)
-- データセットのクエリを修正
SELECT ...
FROM company_curated.daily_sales
WHERE order_date >= date_add('day', -90, current_date)  -- 直近90日のみ

-- 2. 集計レベルを上げる
-- 詳細データではなく日次/週次集計を使用
SELECT
    date_trunc('week', order_date) as week,
    category,
    SUM(total_sales) as weekly_sales
FROM company_curated.daily_sales
GROUP BY date_trunc('week', order_date), category

-- 3. Direct Queryモードに切り替え(SPICEを使わない)
aws quicksight update-data-set \
    --aws-account-id ${AWS_ACCOUNT_ID} \
    --data-set-id company-daily-sales \
    --import-mode DIRECT_QUERY

-- 4. SPICE容量の追加購入
-- QuickSightコンソールから追加購入($0.25/GB/月)

-- 5. データセットの分割
-- カテゴリ別に複数のデータセットを作成
-- ダッシュボードでパラメータによる切り替え

8. 設計の考察ポイント

データレイクアーキテクチャ

yaml
3層アーキテクチャの設計原則:

Raw Zone:
  目的: ソースデータの忠実な保存
  形式: CSV, JSON, Avro(ソース形式そのまま)
  保持期間: 長期(Glacierへアーカイブ)
  アクセス: ETLジョブのみ
  注意点:
    - スキーマ変更に対応できるよう柔軟に
    - データリネージのためにメタデータ保持

Processed Zone:
  目的: 分析用に最適化されたデータ
  形式: Parquet(カラムナー形式)
  保持期間: 中期(1-2年)
  アクセス: データエンジニア、アナリスト
  最適化:
    - パーティショニング(日付、カテゴリ等)
    - 適切なファイルサイズ(128MB-1GB)
    - Snappy圧縮

Curated Zone:
  目的: ビジネス指標、集計データ
  形式: Parquet
  保持期間: 長期
  アクセス: 全ユーザー(セルフサービス)
  特徴:
    - ビジネス用語でのカラム名
    - 事前計算されたKPI
    - ドキュメント化されたスキーマ

コスト最適化戦略

1. ストレージ階層化:
   - 頻繁アクセス: S3 Standard
   - 低頻度アクセス: S3 Standard-IA
   - アーカイブ: S3 Glacier

2. Athenaクエリ最適化:
   - パーティショニング: 最大90%のコスト削減
   - Parquet形式: 最大80%のコスト削減
   - 結果キャッシュ: 同一クエリの再実行を防止

3. Glueジョブ最適化:
   - Spot Instances: 最大70%のコスト削減
   - 適切なワーカー数: 過剰プロビジョニング防止
   - ジョブブックマーク: 増分処理

4. QuickSight最適化:
   - SPICEの適切なサイジング
   - ユーザーライセンスの管理
   - セッション容量の活用

9. 発展課題

上級チャレンジ1: リアルタイムデータ取り込み

yaml
# Kinesis Firehoseでリアルタイムログ取り込み

KinesisFirehose:
  DeliveryStreamName: company-access-logs
  S3DestinationConfiguration:
    BucketARN: arn:aws:s3:::company-datalake-xxx
    Prefix: raw/access_logs/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/
    ErrorOutputPrefix: errors/
    BufferingHints:
      SizeInMBs: 128
      IntervalInSeconds: 300
    CompressionFormat: GZIP
    DataFormatConversionConfiguration:
      Enabled: true
      InputFormatConfiguration:
        Deserializer:
          JsonSerDe: {}
      OutputFormatConfiguration:
        Serializer:
          ParquetSerDe:
            Compression: SNAPPY
      SchemaConfiguration:
        DatabaseName: company_raw
        TableName: access_logs
        RoleARN: arn:aws:iam::xxx:role/FirehoseRole

上級チャレンジ2: Lake Formation によるガバナンス

bash
# Lake Formationでデータアクセス制御

# データレイク管理者の設定
aws lakeformation put-data-lake-settings \
    --data-lake-settings '{
        "DataLakeAdmins": [
            {"DataLakePrincipalIdentifier": "arn:aws:iam::xxx:user/datalake-admin"}
        ]
    }'

# テーブルレベルの権限付与
aws lakeformation grant-permissions \
    --principal '{"DataLakePrincipalIdentifier": "arn:aws:iam::xxx:role/AnalystRole"}' \
    --resource '{
        "Table": {
            "DatabaseName": "company_curated",
            "Name": "daily_sales"
        }
    }' \
    --permissions SELECT

# カラムレベルの権限付与(PII保護)
aws lakeformation grant-permissions \
    --principal '{"DataLakePrincipalIdentifier": "arn:aws:iam::xxx:role/MarketingRole"}' \
    --resource '{
        "TableWithColumns": {
            "DatabaseName": "company_processed",
            "Name": "customers",
            "ColumnNames": ["customer_id", "segment", "prefecture"]
        }
    }' \
    --permissions SELECT
# email, name などのPIIカラムは除外

上級チャレンジ3: データ品質チェックの自動化

python
# Glue Data Quality ルール定義

from awsgluedq.transforms import EvaluateDataQuality

# 品質ルールセット
rules = """
Rules = [
    ColumnValues "order_id" Uniqueness > 0.99,
    ColumnValues "customer_id" IsComplete,
    ColumnValues "total_amount" > 0,
    ColumnValues "order_date" matches "\\d{4}-\\d{2}-\\d{2}",
    RowCount > 1000,
    ColumnValues "status" in ["completed", "shipped", "pending", "cancelled"]
]
"""

# 品質チェック実行
quality_result = EvaluateDataQuality.apply(
    frame=orders_dyf,
    ruleset=rules,
    publishing_options={
        "dataQualityEvaluationContext": "orders_quality_check",
        "enableDataQualityCloudWatchMetrics": True,
        "enableDataQualityResultsPublishing": True
    }
)

# 結果に基づいてアクション
if quality_result['Outcome'] == 'Failed':
    # アラート送信、処理停止など
    raise Exception(f"Data quality check failed: {quality_result['FailedRules']}")

10. 想定コストと削減方法

月額コスト概算

サービス使用量月額コスト
S3 Standard500GB$12
S3 Standard-IA1TB$12
S3 Glacier2TB$8
Glue Crawler10時間/月$4
Glue ETL100 DPU時間/月$44
Athena1TB スキャン/月$5
QuickSight5 Author + 20 Reader$165
Data Transfer100GB$9
合計約 $259/月

従来構成との比較

従来構成(RDSレプリカ + 商用BI):
- RDS レプリカ: $200/月
- BIツールライセンス: $500/月
- データエンジニア工数: $800/月相当
- 合計: 約 $1,500/月

データレイク構成:
- 合計: 約 $259/月

コスト削減: 83% (月額 $1,241 削減)

11. 学習のポイント

今回学んだこと

1. S3データレイク設計
   □ 3層アーキテクチャ(Raw/Processed/Curated)
   □ パーティショニング戦略
   □ ライフサイクル管理

2. AWS Glue活用
   □ クローラーによるスキーマ検出
   □ ETLジョブでのデータ変換
   □ Data Catalogによるメタデータ管理

3. Amazon Athena
   □ サーバーレスSQLクエリ
   □ パーティションプルーニング
   □ コスト最適化(スキャン量削減)

4. Amazon QuickSight
   □ SPICE によるパフォーマンス向上
   □ ダッシュボード作成
   □ セルフサービスBI

GCPとの比較まとめ

観点AWSGCP
サーバーレスクエリAthena(S3直接)BigQuery(ストレージ統合)
ETLGlue(Spark)Dataflow(Apache Beam)
価格モデルスキャン量課金スキャン量 or 定額
使いやすさ複数サービス組合せBigQuery一体型

次のステップ

1. 発展学習:
   - Amazon Redshift でのDWH構築
   - Amazon EMR での大規模処理
   - AWS Lake Formation でのガバナンス

2. 実務応用:
   - リアルタイムダッシュボード構築
   - 機械学習パイプライン連携
   - データメッシュアーキテクチャ

3. 認定資格:
   - AWS Certified Data Analytics - Specialty
   - AWS Certified Solutions Architect - Professional