経理部門から、過去 2 年分の売上を割引コード別に出してほしいと頼まれます。ある会社では、SQL を少し直して再構築するだけで済みます。これまでに読み込んだ注文行がすべて raw テーブルに残っているからです。別の会社では、夜間ジョブが割引列を保持していなかったため、ジョブを修正して本番から 2 年分の履歴を再抽出することになります。
違いは、変換をどこで実行するかです。ETL(extract、transform、load)は、ウェアハウスに届く前に別のエンジンでデータを整形します。ELT(extract、load、transform)は、生データをウェアハウスにコピーし、そこで SQL を使って整形します。この選択が、計算コスト、データの鮮度、ロジックの変更しやすさ、個人データの置き場所を決めます。
この記事では、2 つのパイプラインの仕組みを順に説明して比較し、ETL がいまも有利な場面と一般的なハイブリッド構成を示したうえで、並べて比較する図で締めくくります。
ETL パイプラインの仕組み
ETL では、ソースとウェアハウスの間に変換エンジンが入ります。夜間の 1 回の実行は次のように進みます。
- 抽出(Extract):新規および変更された行を、
updated_at列に対するクエリ、または change data capture のストリームから取り出します。 - 変換(Transform):エンジン上で値のクレンジング、重複の除去、参照データの結合、個人データのマスキングを行い、結果をファクトテーブルとディメンションテーブルに整形します。
- 読み込み(Load):結果を insert または merge でウェアハウスに読み込みます。
エンジンには、Informatica、SQL Server Integration Services(SSIS)、Spark ジョブ、Python スクリプトなどを使えます。生の抽出データはステージング領域に置かれ、ジョブが成功すると消去されることが多いため、ジョブが想定していなかった質問にはウェアハウスが答えられません。
ELT パイプラインの仕組み
ELT では、変換処理をウェアハウスが担当します。
- 抽出と読み込み。 Fivetran や Airbyte などのローダーが、ソーステーブルをほぼそのまま
rawスキーマにコピーします。このとき_fivetran_syncedや_airbyte_extracted_atのようなメタデータ列を追加し、各行がいつ同期されたかを記録します。 - 変換。 通常は dbt で管理する SQL モデルが raw テーブルを読み、クレンジングと結合を済ませたテーブルを別のスキーマに作ります。
- 提供。 BI ツールが最終テーブルを参照します。最終テーブルは通常、mart と呼ばれます。
ELT は、BigQuery や Snowflake のようにストレージとコンピュートを分離したクラウドウェアハウスとともに広まりました。生のコピーを保持するコストは低く、変換の処理能力はウェアハウスに合わせて拡張できます。読み込んだ行がすべて残るので、モデルの修正、列の追加、新しい指標の定義を行い、ソースに触れずに履歴から再構築できます。
ETL と ELT の比較
| ETL | ELT | |
|---|---|---|
| 変換の実行場所 | ウェアハウスの手前にある別のエンジン | ウェアハウスの中(SQL) |
| ウェアハウスに入るもの | モデル化済みのテーブルのみ | raw テーブル、続いてモデル化済みのテーブル |
| 生データの保持 | まれ。抽出データは消去される | あり。raw スキーマに保持 |
| ソースの新しい列 | 誰かがマッピングするまで無視される | ローダーが raw テーブルに追加できる。モデルで使うには SQL の編集が必要 |
| ビジネスロジックの変更 | ジョブを編集し、履歴を再抽出する | SQL を編集し、raw から再構築する |
| 計算コスト | エンジンのサーバーまたはクラスター、加えてウェアハウス | モデル実行ごとのウェアハウス計算、加えて raw のストレージ |
| 個人データ | 到着前にマスキングされる | そのまま到着する。ローダーがマスキングする場合を除く |
| 鮮度 | ジョブ全体が終わったときに更新される | 生データはローダーのスケジュール、mart はモデルの実行時 |
| 代表的なツール | Informatica、SSIS、AWS Glue、Spark | Fivetran または Airbyte、dbt、そして BigQuery、Snowflake、Redshift または Databricks |
略語よりスケジュールのほうが重要です。Fivetran のデフォルトの同期は 6 時間ごとに実行されるため、1 時間ごとの ETL ジョブより鮮度は低くなります。
ETL がいまも有利な場面
- 個人データを生のまま置けない場合。 平文のメールアドレスやカード番号をウェアハウスに入れてはならないなら、読み込み前にマスキングします。ウェアハウスのマスキングポリシーは保存内容を変えません。Snowflake の Dynamic Data Masking(Enterprise Edition の機能)は、クエリ時に平文の値をマスキングします。
- ターゲットが変換できない場合。 容量が固定された旧式のウェアハウス、検索インデックス、パートナーへのファイル受け渡しは、完成したデータを前提としています。
- SQL が苦手とする加工(行ごとの API 呼び出し、ジオコーディング、PDF 解析、モデルによるスコアリングなど)は、Python や Spark のほうが向いていることが多くあります。
- 低レイテンシが求められるストリーミング。 Apache Flink や Kafka Streams は、イベント発生の数秒後に変換します。どこから読むかは Kafka アーキテクチャ図で確認できます。
- 保持したくないデータ量。 1 秒に 1 回測定する 10,000 台のセンサーは、1 日に 8 億 6,400 万行(10,000 × 86,400)を生成します。読み込み前に 1 分平均を計算すれば、1,440 万行(10,000 × 1,440)まで減り、60 分の 1 になります。
一般的なハイブリッド構成
実際には、多くの ELT パイプラインが読み込みの前に小さな変換を挟んでおり、これは EtLT と書かれることもあります。生のまま置いてはならないものだけを転送中に変換し、それ以外はすべてウェアハウスで行います。ウェアハウスならバージョン管理、テスト、再構築が簡単です。
個人データについては、Fivetran のカラムハッシュが、同期中に SHA-256 と宛先ごとのソルトで列をハッシュ化するため、ハッシュ化したメールアドレスでも結合できます。データブロッキングは列そのものを除外します。Airbyte の mappings は、ストリームごとにフィールドをハッシュ化または暗号化できます。どのツールでも、ソルト付きハッシュを選んでください。メールアドレスのソルトなしの SHA-256 は、既知のアドレス一覧と照合されるおそれがあります。注意点がさらに 2 つあります。ハッシュ化が適用されるのは今後の同期だけなので、履歴には再同期が必要です。また、ソルト付きハッシュは仮名化であって、匿名化ではありません。GDPR では、仮名化されたデータも個人データのままです(前文第 26 項)。この記事は法的助言ではありません。公式の条文をプライバシー担当チームと一緒に読み、個人データの流れを示すデータマップを維持してください。
レイヤー構造の SQL モデルによる ELT
dbt のプロジェクト構成ガイドでは、どの SQL ツールでも使える 3 つのレイヤーが説明されています。
| レイヤー | 役割 | マテリアライズ方法 | 参照元 |
|---|---|---|---|
| Staging | ソーステーブルごとに 1 モデル(例:stg_shop__orders)。列名の変更、型のキャスト、セントからドルへの変換を行い、結合や集計は行わない |
ビュー | 他のモデル |
| Intermediate | 目的別の中間ステップ(例:注文明細を注文単位にまとめる) | エフェメラルモデル、または別スキーマのビュー | 他のモデル |
| Marts | 注文や顧客など、ビジネスエンティティごとに 1 つの幅広いテーブル | テーブルまたはインクリメンタルモデル | BI ツールとアナリスト |
レイクハウスも同じ考え方を、ブロンズ、シルバー、ゴールドという名前で使っています。メダリオンアーキテクチャ図を参照してください。
dbt には 4 つの汎用データテスト(unique、not_null、accepted_values、relationships)が付属しており、失敗した行を返すクエリであれば何でもテストにできます。鮮度チェックは、気づかないうちに止まったローダーを検出します。1 つの source 定義で両方を宣言できます。
sources:
- name: shop
schema: raw_shop
config:
loaded_at_field: _fivetran_synced
freshness:
warn_after: {count: 12, period: hour}
error_after: {count: 24, period: hour}
tables:
- name: orders
columns:
- name: id
data_tests:
- unique
- not_null
dbt source freshness(dbt v2 では dbt freshness)は、最新の _fivetran_synced の値が 12 時間より古いと警告を出し、24 時間を過ぎるとエラーを報告します。
オーケストレーションとデータ品質
オーケストレーターは各ステップを順番に実行します。Airflow では、DAG(依存関係とスケジュールを持つタスクの集まり)がローダーの同期を起動し、その完了を待ってから dbt を実行します。Dagster の dbt 連携は、各 dbt モデルをアセット(存在すべきテーブル)に変換するため、mart が Fivetran の同期で書き込まれるテーブルに直接依存できます。
どちらの場合も、dbt build が不良データをダッシュボードに入れません。モデル、テスト、スナップショット、シードを DAG の順に実行し、テストが失敗すると下流はすべてスキップされます。鮮度チェックと担当チームへのアラートを加えれば、誤ったデータも古いデータも、関係者が気づく前に表面化します。
Reverse ETL(Airbyte では data activation と呼びます)は逆向きに動き、モデル化済みのデータをウェアハウスから CRM やサポートデスクなどのツールにコピーします。執筆時点(2026 年 11 月)では、Hightouch が単体の製品として提供しており、Fivetran(Census を買収)と Airbyte はデータ取り込みに組み込んで提供しています。
ETL と ELT の図
ダイアグラムの内容
- ETL: extract, transform, then load
- ELT: extract, load, then transform in the warehouse
- Warehouse
- Orders DB (Postgres)
- Transform engine (Spark, SSIS)
- fct_orders
- BI dashboards
- Loader (Fivetran, Airbyte)
- raw.orders (as loaded)
- dbt models: staging, intermediate
- marts.fct_orders
- raw rows
- cleaned, conformed rows
- SQL queries
- raw rows, PII hashed
- raw tables
- built tables
図の読み方は次のとおりです。
- 2 つのレーン、同じ両端:同じ Postgres の注文データベースと同じ BI ダッシュボードです。変わるのは中間部分だけです。
- アンバーは変換を示します:ETL ではウェアハウスの手前にある別のエンジン、ELT ではウェアハウス内の dbt モデルのボックスです。
- ウェアハウスのフレームは保存内容を示します。 ETL のフレームには
fct_ordersだけがあり、ELT のフレームには読み込んだままのraw.orders、各モデル、marts.fct_ordersがあります。 - 紫のエッジがハイブリッドです:行が到着する前に、ローダーが個人データをハッシュ化します。
- Markdown ブロックには、ELT の実行順、鮮度のしきい値、BI が読むスキーマが書かれています。
ETL と ELT の図をわかりやすく描くには
- 変換は実行される場所に置きます。 ELT の変換をウェアハウスの外に描くと、最大のコストとリスクが隠れてしまいます。
- ウェアハウスは境界として描きます。 1 つのフレーム内の raw、staging、marts は 1 つのシステム内のスキーマであり、別々のデータベースではありません。
- エッジには流れるもの(生の行、ハッシュ化した行、構築したテーブル)と、必要ならスケジュールを書きます。
- 個人データをマスキングする場所と、平文のまま残る場所を示します。
- すべてのモデルではなく、レイヤーを描きます。 レイヤーごとに例のテーブルを 1 つ置けば十分です。リネージは dbt が生成するドキュメントに任せます。
- 制御フローは分けて描きます。 オーケストレーターのトリガーは破線のエッジで描き、データと間違われないようにします。
CDC、Kafka、ウェアハウスを含むパイプライン全体は、データパイプラインのアーキテクチャ図で確認できます。
Archboard で作る
- Google または GitHub でサインインし、ダイアグラムを作成します。
- 基本パックのフレームノードを 2 つ、ETL と ELT のレーン用に上下に追加し、各レーンの中にウェアハウス用のフレームを同じ水平位置で入れ子にして追加します。
- ETL レーンでは、データパックの Postgres ノード、変換エンジン用の基本のボックス、ウェアハウスのフレーム内の
fct_orders用にデータパックのデータウェアハウスノード、BI 用の基本のボックスを追加します。エッジには raw rows、cleaned and conformed rows、SQL queries とラベルを付けます。 - ELT レーンでは、Postgres ノードと、ローダー用の基本のボックスを追加します。ウェアハウスのフレーム内には、
raw.ordersとmarts.fct_orders用のデータウェアハウスノードを追加し、その間に dbt モデル用の基本のボックスを置きます。最後に BI 用の基本のボックスを置き、エッジには同じようにラベルを付けます。 - 2 つの変換ボックスをアンバーに、ローダーから出るエッジを紫にします。説明が必要なノードの下に基本のテキストのメモと、短い色の凡例を追加します。
- 基本パックの Markdown ブロックを追加し、実行順と鮮度のしきい値を書きます。
パイプラインがすでに Mermaid のフローチャートとして存在する場合は、Mermaid から編集可能なダイアグラムへのツールに貼り付けると、最初のたたき台を作れます。この例で使うダイアグラムノードは 15 個で、Free プランの範囲に収まります。
よくある質問
ETL と ELT の違いは何ですか? 変換をどこで実行するかです。ETL は別のエンジンでデータを変換し、結果だけを読み込みます。ELT は先に生データをウェアハウスに読み込み、そこで SQL を使って変換するため、再構築用に生のコピーが残ります。
ETL は時代遅れですか? いいえ。クラウドウェアハウスでは ELT が通常のデフォルトですが、個人データを到着前にマスキングする必要がある場合、ターゲットが変換できない場合、重い加工や低レイテンシのストリーミングには、ETL がいまも適しています。
dbt は ETL ツールですか? dbt は ELT の T を担当します。ウェアハウス内で SQL モデルとテストを実行しますが、データの抽出と読み込みは行いません。それは Fivetran や Airbyte などのローダーの役割です。
ELT は ETL より安いですか? ボリュームと運用の習慣によります。ELT は別のエンジンが不要になりますが、モデルの実行ごとにウェアハウスの計算料金がかかり、生のコピーも保存します。インクリメンタルモデルならコストを抑えられますが、大きなテーブルを 1 時間ごとに全件再構築するとそうはいきません。
Reverse ETL とは何ですか? モデル化済みのデータをウェアハウスから CRM などの業務ツールにコピーすることです。mart から読み、スケジュールで実行し、他のパイプラインと同じテストと担当者を設けてください。