LESSON 30分

ストーリー

高橋アーキテクト
データは新しい石油だ。だが、原油のままでは使えない。精製するパイプラインが必要だ
高橋アーキテクト
クリックログ、購買履歴、センサーデータ…毎日テラバイトの生データが流れ込む。それを分析可能な形に変換し、適切な場所に格納する。これがデータパイプラインの役割だ

ETL vs ELT

// ETL: Extract → Transform → Load
// 変換してからデータウェアハウスにロード
class ETLPipeline {
  async run(): Promise<void> {
    // 1. Extract: ソースからデータを抽出
    const rawData = await this.extractFromSources();

    // 2. Transform: データを変換・クレンジング
    const transformed = this.transform(rawData);
    // 型変換、欠損値処理、集約、デノーマライズ

    // 3. Load: データウェアハウスに格納
    await this.loadToWarehouse(transformed);
  }
}

// ELT: Extract → Load → Transform
// まずロードしてからウェアハウス内で変換(モダンなアプローチ)
class ELTPipeline {
  async run(): Promise<void> {
    // 1. Extract: ソースからデータを抽出
    const rawData = await this.extractFromSources();

    // 2. Load: データレイクにそのまま格納
    await this.loadToDataLake(rawData);

    // 3. Transform: データレイク/ウェアハウス内で変換
    // dbt等のツールでSQLベースの変換
    await this.transformInWarehouse();
  }
}

const ETL_VS_ELT = {
  etl: {
    bestFor: "構造化データ、明確なスキーマ",
    tools: ["Apache Airflow", "AWS Glue", "Informatica"],
    pros: "データ品質を事前に保証",
    cons: "スキーマ変更に弱い、変換がボトルネック",
  },
  elt: {
    bestFor: "大量データ、スキーマが頻繁に変わる",
    tools: ["dbt", "BigQuery", "Snowflake", "Databricks"],
    pros: "柔軟、スケーラブル、変換を後から追加",
    cons: "ストレージコスト増、データレイクの管理が必要",
  },
};

バッチ処理 vs ストリーム処理

// バッチ処理: 定期的にまとめて処理
interface BatchProcessing {
  schedule: "1時間ごと / 1日ごと";
  latency: "分〜時間単位の遅延";
  tools: ["Apache Spark", "AWS EMR", "Hadoop"];
  useCase: "日次レポート、月次集計、モデル学習";
}

// ストリーム処理: リアルタイムでデータを処理
interface StreamProcessing {
  schedule: "常時(イベント駆動)";
  latency: "ミリ秒〜秒単位";
  tools: ["Apache Kafka", "Apache Flink", "Kinesis Data Streams"];
  useCase: "リアルタイムダッシュボード、異常検知、不正検知";
}

// Lambda Architecture: バッチ + ストリームの組み合わせ
class LambdaArchitecture {
  // バッチレイヤー: 全データを定期的にバッチ処理
  batchLayer = {
    input: "データレイク全体",
    output: "バッチビュー(正確だが遅い)",
    schedule: "毎日or毎時",
  };

  // スピードレイヤー: 新しいデータをリアルタイムで処理
  speedLayer = {
    input: "リアルタイムストリーム",
    output: "リアルタイムビュー(速いが近似)",
    schedule: "常時",
  };

  // サービングレイヤー: バッチビュー + リアルタイムビューをマージ
  servingLayer = {
    query: "バッチビュー + リアルタイムビュー",
    result: "最新かつ正確なデータ",
  };
}

ハイレベル設計

┌────────────────────────────────────────────────────────┐
│                                                        │
│  データソース群                                          │
│  [RDB] [API] [ログ] [IoT] [ファイル]                     │
│     │     │    │      │       │                        │
│     └──────┴────┴──────┴───────┘                        │
│                │                                        │
│         [データ収集層]                                    │
│    Kafka / Kinesis / Fluentd                            │
│                │                                        │
│         ┌──────┴──────┐                                 │
│         ▼             ▼                                 │
│    [バッチ処理]    [ストリーム処理]                        │
│    Spark / EMR     Flink / Kinesis                      │
│         │             │                                 │
│         ▼             ▼                                 │
│    [データレイク]  [リアルタイムDB]                        │
│    S3 / GCS       Redis / DynamoDB                      │
│         │                                               │
│         ▼                                               │
│    [データウェアハウス]                                    │
│    BigQuery / Redshift / Snowflake                      │
│         │                                               │
│         ▼                                               │
│    [BIツール / ダッシュボード]                              │
│    Metabase / Grafana / Tableau                         │
│                                                        │
└────────────────────────────────────────────────────────┘

データ品質の担保

// データ品質チェックの実装
class DataQualityChecker {
  checks = [
    {
      name: "完全性チェック",
      description: "NULLや欠損値の検出",
      rule: (data: Row[]) => data.filter(r => r.userId == null).length === 0,
    },
    {
      name: "一意性チェック",
      description: "重複レコードの検出",
      rule: (data: Row[]) => new Set(data.map(r => r.id)).size === data.length,
    },
    {
      name: "鮮度チェック",
      description: "データの最新性を確認",
      rule: (data: Row[]) => {
        const latestTimestamp = Math.max(...data.map(r => r.timestamp));
        return Date.now() - latestTimestamp < 3600000; // 1時間以内
      },
    },
    {
      name: "整合性チェック",
      description: "参照整合性やビジネスルールの検証",
      rule: (data: Row[]) => data.every(r => r.amount >= 0),
    },
  ];

  async validate(data: Row[]): Promise<QualityReport> {
    const results = this.checks.map(check => ({
      name: check.name,
      passed: check.rule(data),
    }));

    const allPassed = results.every(r => r.passed);
    if (!allPassed) {
      await this.alertService.notify("データ品質アラート", results);
    }

    return { results, allPassed };
  }
}

まとめ

ポイント内容
ETL vs ELTETLは事前変換、ELTはロード後変換。モダンはELT
バッチ vs ストリーム遅延許容ならバッチ、リアルタイムならストリーム
Lambda Architectureバッチ + ストリームのハイブリッド
データ品質完全性、一意性、鮮度、整合性を自動チェック

チェックリスト

  • ETLとELTの違いを説明できた
  • バッチ処理とストリーム処理の使い分けを理解した
  • Lambda Architectureの仕組みを把握した
  • データ品質チェックの重要性を理解した

次のステップへ

次は「分析基盤の設計」を学びます。データウェアハウスとOLAP、ダッシュボードの設計を掘り下げます。


推定読了時間: 30分