この用語ページの主要トピックを一覧から飛べます。
🍰 まずはやさしく
バラバラなデータをまとめる仕組みです。
分析しやすい形に整えるために使います。
部活の出欠簿を1つの表にまとめるような作業です。
ここではETLの定義や便利な道具について読みます。
🍰 まずはやさしく
データの通り道を作る仕事のようなものです。
分析や予測に使える状態にするために使います。
スマホのアプリから情報を集めて整理するイメージです。
ここではETLの流れや歴史について読みます。
論文・業務文書で 「ETL」「ELT」「データパイプライン」「データインジェスチョン」「データ統合」「データクレンジング」「データ変換」 といった表現が出てきたら、 このページです。
ETL はデータエンジニアリングの 「血液循環」。 多様なソース(DB、 ファイル、 API、 ログ)から定期的にデータを集約し、 分析・BI・ML に使える形に整える。 これなしに「データドリブン経営」は成立しません。
本ページでは ETL の 3 工程、 ETL vs ELT、 バッチ vs ストリーミング、 主要ツール、 設計パターン(冪等性、 増分更新、 SCD)、 SSDSE データを使った具体例を網羅します。
🍰 まずはやさしく
料理のレシピのようなものです。
材料を使いやすい形に加工するために使います。
買い物した食材を切って鍋に入れる作業に似ています。
ここでは具体的な処理の手順について読みます。
ETL を 「料理のレシピ」に例えると分かりやすい。 (E) 材料を冷蔵庫から出す、 (T) 切って下味を付ける、 (L) 鍋に入れて煮込む。 料理=完成データ、 材料=ソースデータ、 レシピ=ETL ジョブ。
EC 企業の経営会議で「日次売上ダッシュボード」が必要に。 でもデータが散在:
これらを 毎晩 1 時間で集約して Tableau に流すパイプラインが ETL。
上流の各支流=ソースシステム。 浄水場(ETL)が水を集めて飲める状態に。 河口の貯水池=DWH。 各家庭(BI ツール、 ML モデル)が水を飲む。 浄水場が止まると全部止まる。
本コンペで SSDSE データを使う分析自体が、 実は ミニ ETL です:
pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])df.to_parquet('data/processed/cleaned.parquet') または DB INSERTJupyter ノートブックでの前処理も立派な ETL。 これを「定期実行する」ようにすると本格的なデータパイプラインに。
ETL は Extract(抽出)、 Transform(変換)、 Load(投入)の 3 段階パイプライン。 ここでは「データの流れ」「ELT との違い」「Bronze/Silver/Gold メダリオン構造」を視覚化する。
ETL の 3 工程(Extract / Transform / Load)を SSDSE-B-2026 で具体化する。 設計を読むだけでなく、 動く Python コードに落とすことで「ETL は手書きでも書ける」感覚を身につける。
このコードでやること: SSDSE-B-2026 CSV を読み込み、 必要な列だけを取り出し、 ソース層スキーマに整える。
📥 入力: data/raw/SSDSE-B-2026.csv(cp932 エンコード)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import pandas as pd # Extract: SSDSE-B-2026 は 2012–2023 の複数年を収録するので 2023 年に絞る src = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) src = src[src['SSDSE-B-2026'] == 2023].reset_index(drop=True) keep_cols = ['Code', 'Prefecture', 'A1101', 'A1303', 'A4200', 'B4101'] extract_df = src[keep_cols].rename(columns={ 'Code': 'pref_code', 'Prefecture': 'pref_name', 'A1101': 'pop_total', 'A1303': 'pop_elderly', 'A4200': 'deaths', 'B4101': 'temp_avg', }) print(extract_df.head(3)) print(f'rows: {len(extract_df)}') |
📤 実行例:
💬 列名を英語スネークケースに整え、 後段で扱いやすくする(Bronze 層)。
このコードでやること: 派生指標(高齢化率、 死亡率)を計算し、 ビジネス上の意味のある単位に変換する(Silver 層)。
1 2 3 4 5 6 7 | silver_df = extract_df.assign( elderly_rate=lambda d: (d['pop_elderly'] / d['pop_total'] * 100).round(2), death_rate_permille=lambda d: (d['deaths'] / d['pop_total'] * 1000).round(2), climate_zone=lambda d: pd.cut(d['temp_avg'], bins=[-5, 12, 18, 30], labels=['寒冷', '温暖', '亜熱帯']), ) print(silver_df[['pref_name','elderly_rate','death_rate_permille','climate_zone']].head(5)) |
📤 実行例:
💬 派生指標により「何が高い低い」が一目で分かる形式に。 これが Silver 層の役割。
このコードでやること: SQLite に書き出し、 BI ツールから参照可能な形にする(Gold 層)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import os import sqlite3 os.makedirs('data/warehouse', exist_ok=True) # 保存先が無いと connect は失敗する gold_df = silver_df.groupby('climate_zone', observed=True).agg( n_pref=('pref_code','count'), avg_elderly=('elderly_rate','mean'), avg_death=('death_rate_permille','mean'), ).round(2).reset_index() con = sqlite3.connect('data/warehouse/ssdse_gold.db') gold_df.to_sql('pref_kpi_by_climate', con, if_exists='replace', index=False) print(pd.read_sql('SELECT * FROM pref_kpi_by_climate', con)) |
📤 実行例:
💬 寒冷地ほど高齢化と死亡率が高い。 BI ツールから即座にダッシュボード化できる形式に整形完了。
このコードでやること: 同じ ETL を 2 回実行しても結果が同じ(べき等)であることを保証する仕組み。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import pyarrow # parquet の読み書きに必要(ブラウザには無い) import hashlib, json from datetime import datetime def etl_run_with_audit(src_path, out_path, run_id): df = pd.read_csv(src_path, encoding='cp932') df_hash = hashlib.md5(pd.util.hash_pandas_object(df).values).hexdigest() audit = { 'run_id': run_id, 'rows': len(df), 'hash': df_hash, 'timestamp': datetime.now().isoformat(), } df.to_parquet(out_path) with open(out_path + '.audit.json', 'w') as f: json.dump(audit, f, indent=2) return audit a1 = etl_run_with_audit('data/raw/SSDSE-B-2026.csv', '/tmp/run1.parquet', 'R001') a2 = etl_run_with_audit('data/raw/SSDSE-B-2026.csv', '/tmp/run2.parquet', 'R002') print(f'同じ入力 → 同じハッシュ? {a1["hash"] == a2["hash"]}') |
💬 ハッシュ一致でべき等性を保証。 監査ログがあれば「いつ何を処理したか」を後から追跡可能。
| ETL 段階 | 役割 | 典型データ形式 |
|---|---|---|
| Bronze(生) | 取り込みのみ | JSON / CSV / Parquet |
| Silver(精製) | クレンジング・派生 | Parquet / Delta |
| Gold(集計) | BI 向け集計 | RDB / Cube |
形式がバラバラな 3 つのソース(CSV 風・DB 風・API 風)から、 Extract → Transform → Load の 3 段階でデータが「使える 1 枚のテーブル」に磨かれていく様子をステップ実行で体感できます。 Transform を飛ばす失敗例と ELT(先にロード)もトグルで比較できます。
📊 数値は SSDSE-B-2026(2023 年)の北海道・青森県・岩手県の実測値(総人口 A1101・65 歳以上人口 A1303・年平均気温 B4101)。 デモのために「形式」だけをわざと崩しています(5,092 千人 = 5,092,000 人、 11.0 ℃ = 51.8 °F、 数値そのものは実測のまま)。 NULL・重複・不明コード 99000 はエラー処理を体感するための演出データです。
上のシミュレータで体感できる ETL の本質は 3 つだけ。 (E) 取り出す:ソースには手を加えず、 まず全部ステージングへコピーする(4+4+3 = 11 レコード)。 (T) 整える:型統一("5,092" 千人 → 5,092,000 人)→ 単位換算(51.8 °F → 11.0 ℃)→ キー結合(北海道 = 01000 = Hokkaido)→ クレンジング(重複削除・派生指標)と、 順番にルールを適用する。 (L) 積み込む:検証済みの 3 行だけを DWH に格納する。 「Transform を飛ばす」を試すと、 11 行の混沌がそのまま DWH に入り、 SUM も AVG も計算不能になる — Garbage in, garbage out を目で確認できます。
🍰 まずはやさしく
データを扱うための設計図のようなものです。
間違いのないデータを作るために使います。
テストの点数を集計して平均を出す手順に似ています。
ここでは3つの工程や詳しいルールについて読みます。
ETL の「数式」よりも「設計概念」が中核です。
$$ \text{Data Sources} \xrightarrow{E} \text{Staging} \xrightarrow{T} \text{Transformed} \xrightarrow{L} \text{DWH / DataMart} $$
| 項目 | ETL | ELT |
|---|---|---|
| 順序 | E → T → L | E → L → T |
| 変換場所 | ETL サーバー | DWH 内部 (SQL) |
| DWH 計算力 | 不要 | 強力 (BigQuery, Snowflake) |
| ストレージ | コスト気にする | 安価で「とりあえず保管」 |
| 代表ツール | Informatica, SSIS | dbt, Fivetran |
| 登場時期 | 1990s | 2010s クラウド時代 |
| 柔軟性 | 変換ロジック固定 | SQL で後から組み替え可 |
同じ ETL ジョブを何度実行しても同じ結果になる性質。 「1 行 INSERT」ではなく「重複時 UPDATE(UPSERT)」、 もしくは「日付指定の DELETE + INSERT」で実装。
$$ f(f(x)) = f(x) \quad \text{(冪等性)} $$高水位印(high water mark)方式:
$$ \Delta D = \{ d \in \text{Source} : d.\text{updated\_at} > t_{\text{last\_run}} \} $$| タイプ | 動作 | 用途 |
|---|---|---|
| Type 0 | 変更不可 | 固定マスタ |
| Type 1 | 上書き、 履歴なし | 現在値だけ必要 |
| Type 2 | 履歴を行として保存 | 履歴追跡必須 |
| Type 3 | 現在値と前回値 | 直近の変更だけ知りたい |
| Type 4 | 現在テーブル + 履歴テーブル | HMS パターン |
| Type 6 | Type 1+2+3 のハイブリッド | 柔軟性最大 |
「ETL」は単なる「データ移送」ではなく、 設計原則・実装パターンの体系です。 中身を順に読み解きます。
「とりあえずデータを取ってくる」段階。 ソースシステムに 負荷をかけずに、 抜け漏れなく取ることが大事。 典型的アプローチ:
updated_at > last_run_at で WHERE。 大規模データの定石。ETL で最も ロジックが集中する段階。 やることは:
変換済みデータをターゲット(DWH、 データマート、 ファイル)に書き込む。 重要パターン:
障害・タイムアウト時にジョブを再実行できることが重要。 冪等性(idempotency)=「何度実行しても同じ結果」。 これがないと再実行時に重複行・データ不整合。
2010 年以前は ETL(変換してからロード)が主流。 ETL サーバー(Informatica など)に変換ロジックを集中。 でも:
結果、 ELT(ロード → 変換)が現代の主流。 dbt(data build tool)がデファクト。
SSDSE-B-2026 を題材に、 ETL の典型的な処理を順を追って実装します。
[E] SSDSE-B-2026.csv (cp932) → 読み込み
↓
[T] - 欠損行除去
- 派生変数作成(高齢化率、 病院数密度)
- 単位統一(千分率、 %)
- 都道府県コード正規化
- 異常値検出(IQR ベース)
↓
[L] cleaned.parquet, PostgreSQL の observations テーブル
1 2 3 4 5 6 7 8 9 10 11 | import pandas as pd # Extract(SSDSE-B-2026 は複数年を収録。2023 年分だけに絞る) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True) print(f'Extracted: {df.shape}') # 基本検証 assert df['Code'].nunique() == 47, '47 都道府県でない' assert df['SSDSE-B-2026'].min() == 2023, '年フィルタ失敗' assert not df['Code'].isna().any(), 'コードに NULL' |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import numpy as np # 派生変数 df['aging_rate'] = df['A1303'] / df['A1101'] * 100 # 高齢化率 (%) df['hosp_per_100k'] = df['I510120'] / df['A1101'] * 1e5 # 10万人あたり病院数 df['death_rate'] = df['A4200'] / df['A1101'] * 1000 # 死亡率 (千分率) # 単位確認 assert df['aging_rate'].between(15, 50).all(), '高齢化率が範囲外' # 異常値検出(IQR) def detect_outliers(s): q1, q3 = s.quantile([0.25, 0.75]) iqr = q3 - q1 return (s < q1 - 1.5*iqr) | (s > q3 + 1.5*iqr) for col in ['aging_rate', 'death_rate']: n_out = detect_outliers(df[col]).sum() print(f'{col}: outliers = {n_out}') |
1 2 3 4 5 6 7 8 9 10 11 12 | # wide -> long indicators = ['A1101', 'A1303', 'A4200', 'B4101', 'F3101', 'I510120', 'aging_rate', 'hosp_per_100k', 'death_rate'] long_df = df.melt( id_vars=['SSDSE-B-2026', 'Code', 'Prefecture'], value_vars=indicators, var_name='indicator_code', value_name='value' ).rename(columns={'SSDSE-B-2026': 'year', 'Code': 'pref_code'}) print(long_df.head()) print(f'long format rows: {len(long_df)}') # 47 x 9 = 423 |
1 2 3 4 5 6 7 8 9 | import os os.makedirs('data', exist_ok=True) # 書き出し先を先に作る import pyarrow # parquet の読み書きに必要(ブラウザには無い) import os os.makedirs('data/processed', exist_ok=True) # Parquet は CSV より 10 倍小さく、 100 倍速い long_df.to_parquet('data/processed/ssdse_long.parquet', index=False) print(f'saved: {os.path.getsize("data/processed/ssdse_long.parquet")} bytes') |
1 2 3 4 5 6 7 8 9 10 11 | from sqlalchemy import create_engine, text engine = create_engine('postgresql://user:pass@localhost/ssdse') with engine.begin() as conn: # 対象日(年度)の既存レコードを DELETE(冪等性のため) conn.execute(text('DELETE FROM observations WHERE year = :year'), {'year': 2023}) # 新規 INSERT long_df.to_sql('observations', conn, if_exists='append', index=False, method='multi', chunksize=1000) print('Loaded') |
1 2 3 4 5 6 7 8 9 10 11 12 13 | import datetime from sqlalchemy import text with engine.begin() as conn: conn.execute(text(''' INSERT INTO etl_audit (job_name, status, rows, run_at) VALUES (:job, :status, :rows, :ts) '''), { 'job': 'load_ssdse_b_2026', 'status': 'success', 'rows': len(long_df), 'ts': datetime.datetime.utcnow(), }) |
| フェーズ | 処理量 | 時間 |
|---|---|---|
| Extract (CSV 読み込み) | 47 行 × 112 列 | 0.05 秒 |
| Transform (派生変数、 縦持ち化) | 423 行に変換 | 0.10 秒 |
| Validate (検証) | 制約・異常値チェック | 0.05 秒 |
| Load (Parquet 保存) | 423 行 | 0.20 秒 |
| Load (PostgreSQL UPSERT) | 423 行 | 0.50 秒 |
| 合計 | < 1 秒 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | from airflow import DAG from airflow.operators.python import PythonOperator from datetime import datetime, timedelta default_args = { 'owner': 'data-team', 'retries': 3, 'retry_delay': timedelta(minutes=5), } with DAG('ssdse_etl', schedule='@daily', default_args=default_args, start_date=datetime(2026, 1, 1)) as dag: extract = PythonOperator(task_id='extract', python_callable=extract_ssdse) transform = PythonOperator(task_id='transform', python_callable=transform_data) load = PythonOperator(task_id='load', python_callable=load_to_db) extract >> transform >> load |
合成データで各工程のレコード/秒から全体スループットを計算する。
| 工程 | レコード/秒 |
|---|---|
| Extract | 10,000 |
| Transform | 2,500 |
| Load | 5,000 |
1 2 3 4 5 6 7 | import numpy as np rates = np.array([10000, 2500, 5000]) bottleneck = rates.min() records = 1_000_000 time_s = records / bottleneck print(f"ボトルネック: {bottleneck} rec/s") print(f"処理時間: {time_s} 秒 ({time_s/60:.1f} 分)") |
💬 手計算 (Step 2) 400 秒と Python 出力が完全一致。
SSDSE-B-2026 を pandas だけで Extract → Transform → Load する最小 ETL。
data/raw/SSDSE-B-2026.csv, output directory。
cleaned.parquet, 監査ログ。
小規模データなら pandas で十分。 中規模以上は Dask、 Spark へ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import pyarrow # parquet の読み書きに必要(ブラウザには無い) import pandas as pd, os from datetime import datetime def extract(): return pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) def transform(df): df = df.dropna(subset=['A1101', 'A1303']) df['aging_rate'] = df['A1303'] / df['A1101'] * 100 return df def load(df, path): os.makedirs(os.path.dirname(path), exist_ok=True) df.to_parquet(path, index=False) def etl(): df = extract() df = transform(df) load(df, 'data/processed/cleaned.parquet') print(f'ETL done at {datetime.now()}, rows={len(df)}') if __name__ == '__main__': etl() |
PostgreSQL に冪等な UPSERT で書き込む。 同じ日の再実行でも重複しない。
DataFrame、 接続文字列。
テーブル状態のログ、 affected rows 数。
BigQuery の MERGE、 MySQL の INSERT ... ON DUPLICATE KEY UPDATE と同概念。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from sqlalchemy import create_engine from sqlalchemy.dialects.postgresql import insert engine = create_engine('postgresql://user:pass@localhost/ssdse') def upsert(df, table_name, key_cols): with engine.begin() as conn: for _, row in df.iterrows(): stmt = insert(table_name).values(**row.to_dict()) stmt = stmt.on_conflict_do_update( index_elements=key_cols, set_={c: stmt.excluded[c] for c in df.columns if c not in key_cols} ) conn.execute(stmt) |
Airflow DAG で ETL ジョブを毎日決まった時刻に自動実行。 失敗時はリトライ、 アラート。
DAG ファイル、 Airflow Web UI/CLI。
ジョブ実行履歴、 SLA 監視、 Slack 通知。
業界標準のオーケストレーター。 Prefect、 Dagster が新興競合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from airflow import DAG from airflow.operators.python import PythonOperator from airflow.utils.dates import days_ago from datetime import timedelta with DAG( 'ssdse_etl', schedule='0 2 * * *', # 毎日 2:00 start_date=days_ago(1), catchup=False, default_args={'retries': 3, 'retry_delay': timedelta(minutes=5)}, ) as dag: PythonOperator(task_id='extract', python_callable=extract) PythonOperator(task_id='transform', python_callable=transform) PythonOperator(task_id='load', python_callable=load) |
クラウド DWH 内で SQL モデルを段階的にビルド。 Jinja テンプレートで再利用性も高い。
models/*.sql、 dbt_project.yml、 BigQuery / Snowflake 接続。
ビルド済みテーブル、 自動生成ドキュメント、 系譜図 (lineage)。
2020 年代の ELT 標準。 「データチーム版 Git」。 Open Source 版と Cloud 版あり。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | -- models/staging/stg_ssdse.sql {{ config(materialized='view') }} SELECT "SSDSE-B-2026" AS year, Code AS pref_code, Prefecture AS pref_name, A1101 AS population, A1303 AS elderly, A1303 / NULLIF(A1101, 0) * 100 AS aging_rate FROM {{ source('raw', 'ssdse_b_2026') }} -- models/marts/death_rate_analysis.sql {{ config(materialized='table') }} SELECT s.pref_name, s.aging_rate, s.A4200 / NULLIF(s.A1101, 0) * 1000 AS death_rate FROM {{ ref('stg_ssdse') }} s WHERE s.year = 2023 |
数 TB クラスの ETL を分散処理。 PySpark で書ける。 SSDSE 規模では Overkill だが、 学習用。
spark-submit、 S3 上の CSV、 cluster 設定。
Parquet 出力、 Spark UI 上の実行プラン。
クラウド DWH ELT の隆盛で Spark の利用は減少傾向。 ただし非構造化データやストリーミングでは依然主力。
1 2 3 4 5 6 7 8 9 10 | from pyspark.sql import SparkSession from pyspark.sql.functions import col, when spark = SparkSession.builder.appName('ssdse-etl').getOrCreate() df = spark.read.csv('s3://my-bucket/ssdse/SSDSE-B-2026.csv', header=True, encoding='shift_jis') df = df.withColumn('aging_rate', col('A1303') / col('A1101') * 100) df = df.withColumn('death_rate', col('A4200') / col('A1101') * 1000) df.write.mode('overwrite').parquet('s3://my-bucket/processed/ssdse.parquet') |
ETL 出力データに期待値テスト(assertion)を入れて、 異常があれば検知。 「データの単体テスト」。
expectations suite JSON、 検証対象 DataFrame。
検証レポート HTML、 pass/fail フラグ。
本番 ETL に組み込み、 失敗時は下流ジョブを止める。 データ品質の最後の砦。
1 2 3 4 5 6 7 8 9 10 11 12 | import pyarrow # parquet の読み書きに必要(ブラウザには無い) import great_expectations as gx ctx = gx.get_context() df = pd.read_parquet('data/processed/cleaned.parquet') gd = ctx.sources.pandas_default.read_dataframe(df) gd.expect_column_to_exist('aging_rate') gd.expect_column_values_to_be_between('aging_rate', min_value=15, max_value=50) gd.expect_column_values_to_not_be_null('pref_code') result = gd.validate() print('success:', result.success) |
CAP 定理、 BASE 特性、 イベンチュアル整合性。 ETLを本格活用する基礎理論。
機能を小さなサービスに分割し、 独立にデプロイ・スケールする設計。 ETLとの親和性が高い。
Kafka、 Kinesis、 EventBridge。 非同期メッセージングで疎結合を実現。
Istio、 Linkerd。 サービス間通信のセキュリティ・可観測性・制御を統一。
Terraform、 Pulumi、 CDK で ETLを Python/TypeScript で記述。
「ネットワーク内も信頼しない」モデル。 BeyondCorp、 ZTNA。
クラウドコスト最適化を組織横断で取り組む文化・プロセス。
ETLを含む社内開発者プラットフォームを構築する専門領域。 近年急成長。
ETL(Extract Transform Load)は、 現代のデータシステム・AIシステムにおいて避けて通れない基盤技術です。 本ページでは、 概念・原理・実装・運用・コスト・ガバナンス・事例を体系的に整理しました。 ここまで読み切ったあなたは、 入門者から実務者へのステップを踏み出したと言えます。
次のステップは:(1) 実際に手を動かす(クラウドの無料枠で試す)、 (2) 関連用語ページを横断学習、 (3) 公式ドキュメント・コミュニティで深掘り、 (4) 認定資格取得、 (5) 本コンペの過去論文に応用、 のいずれか。 「触って慣れる」が最大の学習効率です。
最後に — 本用語ページが、 あなたのデータサイエンス・ソフトウェア開発キャリアの一里塚となることを願います。 関連リンクから次のテーマへ進んでください。
ETLを扱うシステム設計でよく使われる定石パターンを 15 種紹介します。 名前を覚えておくとレビューや設計議論で役立ちます。
アプリが直接キャッシュとデータストアの両方を制御。 ヒット時はキャッシュから、 ミス時は DB → キャッシュ更新。 Redis、 Memcached で頻出。
書き込み時にキャッシュと DB の両方を同時更新。 整合性◎だがレイテンシ高。
書き込みはキャッシュへ即時、 DB へは非同期。 高速だがデータロスリスク。
下流サービス障害時に、 一定回数失敗で「回路を開いて」即時失敗を返す。 連鎖障害を防ぐ。 Hystrix、 resilience4j。
失敗時に指数関数的に間隔を空けて再試行。 Thundering herd を防ぐ。 jitter(揺らぎ)を加えるのが定石。
船の隔壁のように、 リソースを分離して 1 障害が全体に波及するのを防ぐ。 スレッドプール分割、 専用接続プール。
分散トランザクションを補償アクション付きの一連のローカルトランザクションに分解。 Orchestration / Choreography の 2 パターン。
書き込み(コマンド)と読み込み(クエリ)を別モデルで扱う。 性能とスケーラビリティ向上。
状態ではなくイベントを保存し、 再生で状態を導出。 完全な監査履歴、 時間遡及が可能。
レガシーシステムを少しずつ新システムに置換。 ファサードで両方をラップし、 段階的に新へ移行。
外部システムの「変なモデル」が自社モデルを汚染しないよう、 境界に変換層を置く。 DDD の重要パターン。
メインコンテナの横に補助コンテナをデプロイ。 ロギング、 監視、 プロキシなど共通機能を分離。 Istio のエンボイ。
/health エンドポイントで生存・準備状態を報告。 K8s の liveness/readiness probe、 ALB の health check で利用。
分散環境で 1 つのインスタンスをリーダーに選ぶ。 Zookeeper、 etcd、 Raft アルゴリズム。
データを複数ノードに分散。 範囲シャーディング、 ハッシュシャーディング、 ディレクトリベース。 NoSQL の基本。
ETLを採用する前に、 代替手段との性能・コスト・機能比較は欠かせません。 主要な評価軸を整理します。
行=候補製品、 列=必須機能/推奨機能/差別化機能。 ◎/○/△/× で評価し、 重みづけ合計でランキング。 「必須機能 1 つでも × があれば除外」の原則。
標準的フォーマット・プロトコルへの準拠度、 データエクスポート可能性、 サードパーティ移行ツールの有無。 ベンダーロックインを最小化する選定が中長期的に重要。
2〜4 週間の短期検証で、 上記指標を実データ・実運用条件で測定。 「期待値以下」のリスクを早期発見。 PoC 成功 = 本番成功ではないが、 PoC 失敗 = 本番失敗の高確率予測。
ETLについて転職面接で問われやすい質問と模範回答。 ジュニア〜ミドル向け。
概念の本質を一言で。 「〜の目的で、 〜を〜のように行う技術/サービスです」のフォーマット。 専門用語に頼らず、 中学生にも分かる言葉で。
前世代の技術の限界、 ハードウェア・ソフトウェアの進化、 社会ニーズの変化、 を 1 分程度で説明できると◎。
最低 3 つ挙げ、 それぞれの強み・弱み・適用シーン。 自社で使っている/使ったことがある技術を具体的に。
STAR フレームワーク(Situation, Task, Action, Result)で答える。 具体的な数字(規模、 性能改善率、 コスト削減額)が説得力。
「動かない」「遅い」「コスト爆増」など typical なケースから 1 つ選び、 原因究明プロセスと解決策を時系列で。
認証・認可・暗号化・監査ログの 4 観点。 自社で取った対策、 業界標準(OWASP, NIST CSF)の引用ができれば◎。
RI、 スポット、 不要リソース停止、 階層化など、 具体的な削減施策と効果を金額で。
「現状ボトルネックの特定→水平/垂直スケール選択→分散アーキテクチャ移行」の 3 段。 アムダールの法則、 CAP 定理に触れられると◎。
「メトリクス・ログ・トレース」の 3 本柱、 SLI/SLO/SLA、 エラーバジェット、 オンコール体制について。
ソースコード管理、 ビルド、 テスト、 セキュリティスキャン、 デプロイの各段階で使用ツール。
「検知→緩和→復旧→ポストモーテム」の流れ。 非難なし文化、 5 Why's など。
機能、 性能、 コスト、 学習曲線、 コミュニティ、 ベンダーロックイン回避。 個人の好みではなく、 ビジネス価値で判断。
業界で確立された定石と、 やってはいけないこと。 自分が経験した「アンチパターン」を素直に語れると経験値が伝わる。
業界ニュース、 主要カンファレンス(AWS re:Invent, Google Cloud Next など)の発表、 学術論文の動向。 自分の見解も添える。
企業の事業課題と ETL の特性を結びつける。 「御社の〜という課題に対し、 〜という形で貢献したい」。
ETL領域には複数の主要ベンダーが存在し、 それぞれ強み・弱み・エコシステムが異なります。 採用検討時に押さえるべきポイントを整理。
| 評価軸 | 重み | ベンダーA | ベンダーB | ベンダーC |
|---|---|---|---|---|
| 機能網羅性 | 20% | ◎ 95 | ○ 85 | △ 75 |
| 性能 | 15% | ◎ 92 | ◎ 90 | ○ 88 |
| 価格 | 20% | △ 70 | ○ 80 | ◎ 88 |
| サポート | 10% | ◎ 90 | ○ 85 | △ 75 |
| ロックイン回避 | 10% | △ 60 | ○ 70 | ◎ 85 |
| 学習容易性 | 10% | ○ 80 | ◎ 88 | ○ 78 |
| コミュニティ | 10% | ◎ 90 | ○ 80 | ○ 78 |
| セキュリティ認証 | 5% | ◎ 95 | ◎ 92 | ○ 85 |
| 加重平均 | 100% | 82.3 | 83.8 | 82.1 |
1 ベンダーへの依存リスクを下げるため、 主要ワークロードを 2 ベンダーに分散する戦略。 災害時の事業継続、 価格交渉力、 イノベーション選択肢を確保。 ただし運用複雑性・スキル要件は増大する。
ETLは世界的トレンドですが、 日本市場特有の事情を理解することも重要です。
大企業:慎重派が多い。 セキュリティ・コンプライアンスを重視し、 PoC を半年〜1 年かけて実施。 中小企業:意思決定が速いがリソース不足。 自治体:政府ガイドラインに従って慎重に。
海外発の技術は、 日本語ドキュメントが英語より遅れることが多い。 公式日本語サポート、 日本人エンジニアの執筆ブログ、 国内コミュニティ(JAWS-UG、 Cloud Native Days Tokyo など)の活用。
メルカリ、 サイバーエージェント、 LINE、 楽天など IT 出身企業はクラウドネイティブ。 製造業ではトヨタ、 ホンダ、 コマツが先進事例。 銀行ではみずほ、 三井住友、 SBI が積極派。
ETLを学ぶ際の、 日本語環境での推奨学習リソースを段階別に整理します。
ETLに関連するキャリア:(1) 専門エンジニア、 (2) アーキテクト、 (3) テックリード、 (4) コンサルタント、 (5) ベンダー社員、 (6) 教育・トレーナー、 (7) 起業家。 5 年計画で 1 つに絞り、 2-3 年でステップアップ。
ETL を中心とした概念ツリー:
データ統合パイプライン ├─ ETL (Extract-Transform-Load) ← この用語 │ ├─ Extract │ │ ├─ フルロード │ │ ├─ 増分更新 │ │ ├─ CDC │ │ └─ API/ファイル │ ├─ Transform │ │ ├─ クレンジング │ │ ├─ 結合 │ │ ├─ 派生指標 │ │ ├─ 集計 │ │ └─ マスキング │ └─ Load │ ├─ INSERT │ ├─ UPSERT │ ├─ TRUNCATE+INSERT │ └─ パーティション置換 ├─ ELT (Extract-Load-Transform) ├─ Reverse ETL (DWH → SaaS) └─ EL(Extract & Load only) 実行形態: ├─ バッチ (Airflow, Cron) ├─ マイクロバッチ (Spark Structured Streaming) └─ ストリーミング (Flink, Kafka Streams) ツール: ├─ Informatica, SSIS, Talend (商用) ├─ Apache NiFi, Airbyte (OSS) ├─ Fivetran, Stitch (SaaS) └─ dbt (Transform 専用)
ETL の歴史を整理。
企業内データを統合する Enterprise Application Integration。 COBOL でバッチ処理、 磁気テープでデータ移送。
RDB の普及。 「データを 1 箇所に集める」発想で ETL の概念が固まる。 ETL ツールが登場し始める。
Bill Inmon が「Building the Data Warehouse」(1992) を出版。 Ralph Kimball がディメンショナルモデリング (1996)。 Informatica PowerCenter (1993)、 IBM DataStage、 Microsoft SSIS など商用 ETL ツールが市場形成。
Talend (2005)、 Pentaho Kettle、 CloverETL などのオープンソース ETL が普及。 商用ライセンス費を下げる選択肢に。
Hadoop MapReduce、 Hive、 Pig で TB-PB 規模の ETL が可能に。 Spark (2014) で速度が劇的に改善。 Apache NiFi (2014)、 Airflow (2015) が登場。
BigQuery (2010)、 Redshift (2012)、 Snowflake (2014) の登場で、 「DWH の中で SQL で変換」する ELT パラダイムが浮上。 Fivetran (2012)、 Stitch (2013) が EL を SaaS 化。 dbt (2016) で Transform 専用ツールが標準化。
Fivetran + Snowflake + dbt + Tableau の「モダンデータスタック」が業界標準。 SQL ベースの ELT が主流に。 一方で Streaming(Kafka、 Flink)、 Reverse ETL(Hightouch、 Census)も台頭。
2000 年代に商用 ETL(Informatica、 DataStage)が大手企業に普及。 2010 年代後半にクラウド DWH と dbt が浸透し始めるが、 欧米より 5 年遅れ。 トレジャーデータ、 Trocco(日本発 SaaS)も活用される。
ETL 実装の細部。
「1 つの巨大ジョブ」vs 「多数の小ジョブ」。 後者が再実行・並列化・監視で有利。 1 ジョブ=1 テーブル変換、 が定石。
Source → Staging → DWH の 2 段構え。 ステージングは「変換前の状態」を保持し、 再変換が容易。 S3 / GCS の生 Parquet が定番。
ソースのスキーマ変更を検知。 Avro / Protobuf + Confluent Schema Registry。 ETL ジョブの破綻を未然に防ぐ。
CSV では全部文字列。 適切に型推定して変換。 日付フォーマット統一(ISO 8601)。 NULL の表現統一。
ETL 運用での難題。
深夜バッチが朝までに終わらない、 早朝の他ジョブと競合。 SLA 厳守と並行度のバランス。
「この数値はどこから来た?」を即答できる体制。 dbt の autodocs、 Apache Atlas、 OpenLineage。
ジョブ失敗時の再実行。 冪等性必須。 Backfill(過去分の再計算)も視野に。
ソースのスキーマ変更、 値の分布変化を自動検知。 ML モデルへの影響を回避。
「いつ・誰が・どこから・何を・どこへ」を記録。 SOX 法対応、 GDPR の権利行使対応。
ETL のコスト構造。
| ツール | 料金 | 規模 |
|---|---|---|
| Apache Airflow | 無料 | セルフホスト |
| dbt Core | 無料 | SQL モデル |
| dbt Cloud | $100-1,000+/月 | チーム規模 |
| Fivetran | 行数課金、 $1,000+/月 | SaaS |
| Stitch | 行数課金 | SaaS |
| Talend | 無料 / 商用 | エンタープライズ |
| Informatica | $50,000+/年 | 大企業 |
BigQuery:スキャンバイト課金($5/TB)。 Snowflake:仮想ウェアハウス時間課金。 100 GB を毎日変換 → 月 $15。 大規模になると数千ドル。
S3 Standard $0.023/GB。 1 TB のステージング保管で月 $23。 ELT 時代は「とりあえず全部保管」する傾向強。
データエンジニア 1 名 ¥800-1,500 万円/年。 中規模パイプラインで 2-5 名チーム。 学習コスト:ジュニア → 中堅 1-2 年。
ETL のガバナンス。
各テーブル・カラムの所有部門を明確化。 DataHub、 Atlan のような Data Catalog ツールで管理。
PII(個人特定情報)のマスキング、 匿名化、 暗号化。 GDPR、 個情法、 CCPA に準拠。
ETL 実行履歴を 7 年保管(SOX 法)。 誰が・いつ・何を変更したか追跡。
「指標 X はテーブル Y のカラム Z から計算」を機械可読で記録。 OpenLineage 標準。
「完全性 99.9%」「適時性 1 時間以内」など SLA 定義。 great_expectations でテスト自動化。
全世界 4 億ユーザーの再生イベントを Kafka で受け、 Spark で集計、 BigQuery と S3 にロード。 毎日数百 TB を処理。 推薦アルゴリズム、 ロイヤリティ計算、 アーティスト分析の基盤。 「データドリブンな音楽配信」を支える ETL。
予約・宿泊・レビュー・検索の各種データを Airflow で統制し、 Druid / Presto / Hive に格納。 Airflow は Airbnb 発祥のオーケストレーター。 日次で数百ジョブが実行される。
視聴ログ・評価・検索を Kafka + Flink でリアルタイム処理。 + 日次バッチで深層学習モデルを再学習。 ETL の規模は世界最大級。
数百万の加盟店の決済データを CDC(PostgreSQL の WAL)でリアルタイム抽出。 Kafka 経由で各種データマートに配信。 不正検知、 監査、 経理連携。
全国 1,000 店舗の POS データを毎晩本社に集約。 オンプレ Informatica から AWS Glue + Redshift に移行する案件が増加中。 商品マスタ・顧客マスタの統合が課題。
総務省統計局・厚労省・国土交通省などが集めた個票データを、 集計・匿名化・公開可能な形に整える ETL。 SSDSE データもこのプロセスを経て公開される。 国民の血税で運営される公共 ETL。
ETL(Extract, Transform, Load)を実務で扱う際、 教科書には載っていない / 載っていても薄い「現場で効くトピック」をまとめます。 ここを押さえると、 ジュニア → ミドル → シニアの溝を越えられます。
まず 「測ってから改善」が鉄則。 推測でいじっても効果は薄い。 段階的に:
ETL の文脈でも、 たとえばデータの再計算を毎回行うのか、 部分更新で済ませるのか、 という設計判断で 10〜100 倍の性能差が出ます。 「動くものを早く作る → 計測 → 最適化」のサイクルを回す。
本番運用では 「3 本柱」と呼ばれる 3 種類のテレメトリを揃えるのが標準:
SLI(Service Level Indicator)・SLO(Service Level Objective)・SLA(Service Level Agreement)を定義し、 エラーバジェットを管理する SRE プラクティスが現代的標準。
ETL を扱うシステムでも、 通常のソフトウェアと同じテストピラミッドが効きます:
データ系では追加で:データ品質テスト(great_expectations, pandera, dbt test)、 回帰テスト(モデル更新時の予測精度確認)、 負荷テスト(locust, k6)も必須。
継続的インテグレーション (CI) と継続的デプロイ (CD) を整備すると、 変更のリスクが激減します。 標準的な段階:
障害が起きたときの対応プロセス:
DAMA 国際標準では、 データ品質を 6 つの次元で測る:
SSDSE のような公的データでも、 列の意味変更・分類体系の更新があるので、 都度バリデーションを通す。
個人情報を扱う ETL 系のシステムでは:
ETL は以下の国際規格・ガイドラインと接続します:
監査対応では SOC 2 Type II 報告書、 ISMS 認証取得などが営業要件になることも多い。
大規模な ETL システムは電力消費が大きく、 CO₂ 排出が問題視されつつあります。 対策:
ETL を専門にする人のキャリアパス:
学習の順序:基礎理論 → 主要ツール 1〜2 個の深掘り → 周辺ツールの広掘り → 設計パターン → 組織論。 焦らず段階的に。
本番環境にデプロイする前に必ず通したいチェックリストです。 一項目でも飛ばすと事故率が跳ね上がります。
| ツール | タイプ | ライセンス | 強み | 弱み |
|---|---|---|---|---|
| Apache Airflow | オーケストレータ | OSS | Python ベース、 業界標準 | セットアップ大変 |
| dbt | Transform | OSS + SaaS | SQL only、 学習容易 | E/L は別途必要 |
| Fivetran | EL SaaS | 商用 | コネクタ豊富、 マネージド | 行数課金で高価 |
| Apache Spark | ETL エンジン | OSS | 大規模分散、 多言語 | 運用複雑 |
| Apache Kafka | ストリーミング | OSS | リアルタイム、 高スループット | 学習曲線急 |
| Informatica | ETL ツール | 商用 | エンタープライズ機能 | 高価 |
| AWS Glue | クラウド ETL | 従量課金 | AWS 統合、 サーバーレス | Spark 知識必要 |
| GCP Dataflow | クラウド ETL | 従量課金 | Apache Beam ベース | クラウド依存 |
| Azure Data Factory | クラウド ETL | 従量課金 | Microsoft 統合 | UI 重い |
| Pentaho/Kettle | ETL ツール | OSS | GUI、 老舗 | モダン感薄 |
A. 両方。 ただし新規プロジェクトなら ELT 中心(dbt 推奨)。 既存システム保守ではまだ ETL も現役。
A. pandas + Airflow が最も学びやすい。 SQL に慣れているなら dbt 推奨。 GUI 派は Talend Open Studio。
A. (a) Airflow Web UI、 (b) Slack 通知、 (c) Grafana + Prometheus、 (d) PagerDuty。 SLA 違反時の即時アラート必須。
A. リアルタイム性が SLA で 1 時間以上 → バッチ。 数分以下 → ストリーミング。 多くの業務は「日次バッチ」で十分。
A. ロジックが複雑(API、 ファイル変換、 NLP)→ Python。 集計・結合中心 → SQL。 dbt は SQL を Jinja で強化。
A. (a) Airflow の自動リトライ、 (b) Dead Letter Queue(DLQ)、 (c) サーキットブレーカー、 (d) Chaos Engineering で耐障害性テスト。
A. (a) 並列化(パーティション別)、 (b) 増分更新化、 (c) Parquet 等列指向化、 (d) パーティションプルーニング、 (e) 中間テーブルキャッシュ。
A. 段階的に統合すべき。 戦略:(1) インベントリ作成、 (2) 重要度ランキング、 (3) 共通基盤への移行、 (4) レガシーの廃止。 半年〜数年のプロジェクト。
A. DWH のデータを業務系 SaaS(Salesforce, Marketo, HubSpot 等)に戻す逆向きの流れ。 Hightouch、 Census が代表ツール。 「データの民主化」と呼ばれる。
A. ジュニア → データエンジニア → シニアデータエンジニア → データプラットフォーム リード → アナリティクスエンジニア → CDO(Chief Data Officer)。 ML エンジニアへの転身も多い。
ETL (Extract Transform Load) は単独のジョブではなく、 複数ソースからの抽出 ・変換 ・ロードを結ぶデータ統合フローである。 ELT との「変換タイミング」、 dbt ・Airflow との「ジョブ管理」の対比を意識する。
ETL (Extract Transform Load) は「抽出 → 変換 → ロード」の伝統的データ統合手順で、 上流の複数ソースから引き、 並列の ELT と「変換タイミング」で対比し、 下流の DWH・データマートへ整形済みデータを供給する。
ETLの選定・運用での意思決定をツリーで整理。
現状システムに課題があるか?
├─ Yes → 課題はコスト/性能/拡張性/信頼性?
│ ├─ コスト → ROI 試算で ETL 採用検討
│ ├─ 性能 → ベンチマークで比較
│ ├─ 拡張性 → スケーラビリティ要件を整理
│ └─ 信頼性 → SLA, MTBF を比較
└─ No → 「動いているものは触らない」原則
ワークロードの特性は?
├─ 予測可能・常時稼働 → リザーブド/専有
├─ 変動大・短期 → サーバーレス/スポット
├─ レイテンシ厳しい → エッジ/フォグ
└─ コンプライアンス厳しい → プライベート/オンプレ
症状は?
├─ 完全停止 → ロールバック先行、 原因究明は後
├─ 性能劣化 → メトリクス/ログ/トレースで根因分析
├─ コスト急増 → 利用量分析、 不正アクセス疑い
└─ セキュリティイベント → CSIRT 起動、 隔離
ETLを活用した、 あるいは本コンペで再現されている過去論文の例を整理します。
本コンペ参加者の多くが、 公的データを取得→前処理→分析→可視化、 という流れで論文を再現している。 ETLは、 このパイプラインの中で重要な役割を担う。
数百万行のデータを扱う論文では、 ローカル PC では処理時間が長すぎることが多い。 ETLを導入することで、 数時間 → 数分への短縮が可能。
ストリーミングデータを即時に処理する論文。 集計・閾値判定・アラートを ETL的アーキテクチャで実装する。
学習済みモデルを API として公開、 共同研究者・後継研究者が再現可能にする。 ETLを活用したデプロイ。
機密データと公開データを分離して扱う論文では、 ETLの特性を生かしたハイブリッド構成が有効。
以降は本ページ既存の内容を補う「追記ノート」です。 3 工程(Extract・Transform・Load)の直感を短く固め直し、 実務で本当に効く落とし穴を再整理し、 次に学ぶべき発展テーマへ橋渡しします。
ETL とは「散らかった素材を、 分析できる 1 枚の皿に盛り付ける工程」です。
E(Extract=抽出):CSV・DB・API などバラバラの置き場所からデータを引き出す。 「どこから」「いつの分を」取るかを決める段階。
T(Transform=変換):欠損処理・型変換・単位統一・結合・派生指標の計算で、 分析可能な形へ整える。 パイプラインの頭脳。
L(Load=格納):整えたデータを DWH・DB・Parquet など次工程が読める置き場へ書き込む。 ここまで通して初めて「データパイプライン」になる。
ELT との一言違い:ETL は「変換してから格納 (E→T→L)」、 ELT は「先に生データを格納してから、 格納先の計算力で変換 (E→L→T)」。 順序が違うだけだが、 変換をどこで走らせるか(自前サーバか、 クラウド DWH か)という設計思想の違いになる。 詳しくは ELT のページへ。
本コンペの文脈では、 pd.read_csv(...)(E)→ 欠損除去・高齢化率の計算(T)→ to_parquet()(L)という Jupyter 上の前処理が、 そのまま最小の ETL です。 「毎回手で回している前処理を、 定期実行できる形に固める」だけで本格的なパイプラインに育ちます。
既存の「落とし穴 5 件」を、 実務で事故になりやすい観点で 8 点に拡張して補足します。
1. 変換ロジックの複雑化・保守崩壊:T の分岐(例外県・特別集計)が増えるほど、 誰も全体を追えなくなる。 対策は変換の単一ソース化(dbt や 1 モジュールに集約)とテストの併設。 「同じ計算式が Python と SQL と Excel に 3 重」は事故の温床。
2. 増分 (incremental) か フル (full refresh) か:毎回全件を作り直す「フル」は単純で冪等だが遅い・高コスト。 差分だけ足す「増分」は速いが取りこぼし・重複が起きやすい。 まずフルで正しさを担保し、 データ量が痛くなってから増分へ移行するのが安全。
3. 冪等性 (idempotency) の欠如:同じジョブを 2 回流すと行が 2 倍になる設計は危険。 UPSERT(主キーで上書き)または DELETE + INSERT で「何度流しても同じ結果」を保証する。 リトライ・バックフィルの前提。
4. エラー処理・リトライの甘さ:1 件の異常で全件失敗、 あるいは黙って欠損のまま下流へ流す。 異常行は隔離テーブル (quarantine) へ退避し、 一時的失敗は指数バックオフ + jitter で再試行する。
5. データ品質チェックの不在:件数・NULL 率・値域・一意性を検証しないと、 壊れたデータが静かに下流へ。 「行数が前日比 ±50% で警告」「主キー重複ゼロ」など受け入れ検査をパイプラインに埋め込む。
6. スキーマ変更への脆さ:ソース側の列追加・改名・型変更でジョブが突然死。 列を位置ではなく名前で参照し、 想定スキーマとの差分を検知して落とす/通知する仕組みを持つ。 SSDSE でも列名(A1101 等)を明示指定するのはこのため。
7. 依存関係・実行順序の管理不足:「A→B→C」を Cron の時刻だけで並べると、 A が遅延・失敗しても B/C が古い/空のデータで走る。 DAG(依存グラフ)で順序と成否を明示し、 上流失敗時は下流を止める。
8. 監視・アラートの欠如:深夜ジョブの失敗を翌朝まで気づけない。 成功/失敗・所要時間・行数を記録し、 閾値超過で通知する。 「動いているはず」を「動いたと確認済み」に変えるのが運用の肝。
| テーマ | 何が変わるか | 最初の一歩 |
|---|---|---|
| バッチ vs ストリーミング | 「1 日 1 回まとめて」か「発生の都度リアルタイムで」か。 鮮度要件でアーキテクチャが分岐する。 | まずバッチで作り、 秒〜分の鮮度が要るところだけストリーミング化。 |
| 冪等性・再実行 | 失敗・リトライ・バックフィルを安全にする土台。 これが無いと運用が回らない。 | 全ジョブを UPSERT/全置換で「何度流しても同じ」に。 |
| 増分処理・CDC | Change Data Capture でソース DB の変更だけを捕捉。 フル抽出の負荷から解放される。 | 更新日時列やログベース CDC で「前回以降の差分」を抽出。 |
| オーケストレーション | Airflow・Dagster・Prefect で DAG・スケジュール・リトライ・監視を一元管理。 | Cron の羅列を DAG に置き換え、 依存と再実行を宣言的に。 |
| データ品質検証 | great_expectations 等で「期待どおりか」をテスト化。 壊れたら止める文化へ。 | 件数・NULL・値域・一意性の期待値をコードで定義。 |
| ELT との使い分け | 変換を DWH 内で回すと弾力的にスケール。 事前マスキングが要るなら ETL が安全。 | 個人情報・重い前処理は ETL、 分析用整形は ELT と役割分担。 |
| dbt / モダンデータスタック | SQL + テスト + 系譜 + ドキュメントを一体化し、 変換を「単一ソース」で管理。 | ELT の T を dbt モデルとして書き、 Bronze/Silver/Gold で段階整形。 |
学びの順序のおすすめ:まず冪等性(再実行が怖くなくなる)→ データ品質検証(壊れを早期発見)→ オーケストレーション(依存と監視)→ 増分/CDC(規模対応)→ ELT/dbt(モダン化)の順が挫折しにくいです。
本ページ上部の実装例では SSDSE-B-2026.csv を encoding='cp932', skiprows=[1] で読み、 2023 年に絞って 47 都道府県の派生指標を作りました。 このデータは年次で追加されていく性質を持つため、 更新戦略を考える良い題材になります。
| 戦略 | SSDSE-B での具体化 | 向き・不向き |
|---|---|---|
| フル再構築 | 毎回 CSV 全体を読み、 Bronze→Silver→Gold を作り直す。 現状の実装例そのもの。 | 数千行規模なら十分。 冪等で単純、 過去補正も自然に反映。 |
| 増分追記 | 年カラム(例:SSDSE-B-2026 == 2023)をキーに「未取り込みの年だけ」を追加。 | 大規模・高頻度なら有効。 ただし過去年の値が改訂された場合の取りこぼしに注意。 |
この規模での実務判断:SSDSE-B は年次×47 行程度と小さいため、 増分の複雑さを抱えるより毎回フル再構築(=冪等)が正解です。 「増分は速いが難しい」を体感するための思考実験として捉えてください。 上の具体的な処理数値・実行例は本ページ上部の実装セクションを参照(ここでは新規の数値は作りません)。