Apache Airflowとdbt 結局どっちを選ぶべきか

現代のデータ駆動型ビジネスにおいて、信頼性の高いデータパイプラインの構築は成功の根幹をなす要素です。データをある場所から別の場所へ移動させ、ビジネスに役立つ形に変換する。この一連のプロセスは、データエンジニアリングの中核であり、その実現のために多くのツールが登場してきました。特に、モダンデータスタック(Modern Data Stack)の文脈で頻繁に名前が挙がるのが Apache Airflowdbt (Data Build Tool) です。データエンジニアを目指す方や、キャリアの次のステップを考えている方にとって、この二つのツールの違いを理解し、適切に使いこなす能力は非常に重要です。しかし、両者はしばしば比較されながらも、その本質的な役割や思想は大きく異なります。この記事では、フルスタック開発者としての視点から、Airflowとdbtを徹底的に解剖し、「結局どちらを、どのような状況で選ぶべきか」という問いに、明確な答えを提示します。

この比較は、単なる機能の羅列ではありません。それぞれのツールが生まれた背景、解決しようとしている課題、そしてそれらがデータエンジニアのロードマップにどのようにフィットするのかを深く掘り下げていきます。さあ、あなたのデータエンジニアリングの旅を加速させるための知識を探求しましょう。

Apache Airflowとは何か?データパイプラインの指揮者

Apache Airflowは、Airbnbによって開発され、後にApacheソフトウェア財団に寄贈されたオープンソースのワークフロー管理プラットフォームです。その核心的な役割は「オーケストレーション」、つまりデータパイプライン全体の流れを定義し、スケジュールし、監視することにあります。Airflowを理解する上で最も重要なコンセプトは「DAG(Directed Acyclic Graph、有向非巡回グラフ)」です。

Airflow DAGの概念図
AirflowのDAGは、タスク間の依存関係をコードで定義します。

DAGは、一連のタスクとその実行順序、依存関係をPythonコードで定義したものです。例えば、「APIからデータを取得する(タスクA) → 取得したデータをデータレイクに保存する(タスクB) → 保存されたデータを使ってSparkジョブを実行する(タスクC)」といった一連の流れを、グラフ構造として表現します。Airflowは、このDAG定義に従って各タスクを適切なタイミングで実行し、失敗した場合はリトライ処理を行ったり、関係者にアラートを送信したりします。

Airflowの主要コンポーネント

  • Webサーバー: DAGの実行状況を視覚的に確認したり、手動でトリガーしたりするためのUIを提供します。有名な「Graph View」や「Gantt Chart」はここで見ることができます。
  • スケジューラー: DAGの定義を常に監視し、実行されるべきタスクを特定してキューに追加する、Airflowの心臓部です。
  • メタデータデータベース: DAGやタスクの実行状態、接続情報など、Airflowのすべての状態を保存するデータベースです。PostgreSQLやMySQLが一般的に利用されます。
  • エグゼキューター: スケジューラーによってキューに追加されたタスクを実際に実行するコンポーネントです。ローカルで実行するLocalExecutor、分散環境で実行するCeleryExecutorKubernetesExecutorなど、様々な種類があります。

Airflowの最大の強みは、その圧倒的な柔軟性にあります。タスクは基本的にPythonで記述されるため、Pythonで書けることなら理論上は何でもタスクとして実行可能です。APIからのデータ取得、データベースへのクエリ発行、機械学習モデルのトレーニング、インフラのプロビジョニングまで、その用途はETL/ELTプロセスに留まりません。この汎用性の高さが、多くの企業でデータ処理の「ハブ」として採用される理由です。

dbt (Data Build Tool)とは何か?データ変換のスペシャリスト

dbt (Data Build Tool)は、データウェアハウス(DWH)内でのデータ変換(Transformation)プロセスに特化したツールです。dbt Labs(旧Fishtown Analytics)によって開発され、ELTアーキテクチャの「T」の部分を担います。dbtの登場により、アナリティクスエンジニアという新しい役割が生まれるほど、データの世界に大きなインパクトを与えました。

dbtの核心的な思想は、アナリティクスコードにソフトウェアエンジニアリングのベストプラクティスをもたらすことです。具体的には、SQLで書かれたデータ変換ロジックをモジュール化し、バージョン管理、テスト、ドキュメンテーションを容易に行えるようにします。

dbtの主要な特徴

  • SQL as Code: dbtのモデル(変換ロジック)は、基本的にSELECT文で記述されます。これにより、データアナリストなど、SQLに習熟した多くの人々が堅牢なデータ変換パイプラインを構築できます。
  • Jinjaテんプレーティング: SQLにJinjaというテンプレートエンジンを組み合わせることで、if文やforループなどの制御構文を使ったり、変数を埋め込んだり、マクロ(再利用可能な関数)を作成したりと、SQLを動的に生成できます。
  • 依存関係の自動解決: dbtは、ref()という関数を使ってモデル間の依存関係を定義します。例えば、SELECT * FROM {{ ref('stg_users') }}と書くだけで、dbtはstg_usersモデルを先に実行する必要があることを自動的に認識し、正しい順序でモデルを構築してくれます。
  • テスト機能: データの品質を保証するためのテストが組み込まれています。not_nulluniqueといった汎用的なテストから、特定のSQLクエリを書くカスタムテストまで、簡単に定義・実行できます。
  • ドキュメンテーション: dbtは、モデルのコードや定義されたテストから、自動的にデータリネージ(データの血統)を含む美しいドキュメントサイトを生成します。これにより、データがどのように変換されてきたかを誰でも簡単に追跡できます。

dbtは「オーケストレーター」ではありません。dbtはdbt rundbt testといったコマンドを実行すると、定義されたモデルやテストを実行して終了します。定期的に実行するためには、Airflowのような外部のスケジューラーが必要になる、という点が非常に重要です。

根本的な思想の違い:オーケストレーション vs トランスフォーメーション

ここまでで、両者の役割が異なることはお分かりいただけたかと思いますが、ここをさらに深く掘り下げてみましょう。この違いを理解することが、適切なツール選定の鍵となります。

Airflowは、データパイプラインという壮大な建築プロジェクトにおける「ゼネコン(総合建設業者)」です。基礎工事(データ抽出)、鉄骨組立(データロード)、内装工事(データ変換)、電気工事(MLモデル実行)、配管工事(外部API連携)など、様々な専門業者(各種ツールやシステム)を適切な順序で手配し、プロジェクト全体の進捗を管理します。時には自ら簡単な大工仕事(Pythonでのデータ加工)もこなしますが、それが本業ではありません。

フルスタック開発者の視点

一方、dbtは、その建築プロジェクトにおける「宮大工(熟練の木工職人)」です。彼らの仕事は、最高の木材(生データ)を使い、精密な設計図(SQLモデル)に基づいて、寸分の狂いもなく建物の骨格(DWH内のデータマート)を組み上げることです。彼らは他の工事(データ抽出やロード)には関与しませんが、自分の専門分野においては最高の品質と効率を発揮します。

フルスタック開発者の視点

このアナロジーが示すように、Airflowは「何を、いつ、どのような順番で実行するか」というワークフロー全体を管理するのに対し、dbtは「データウェアハウス内で、どのようにデータを変換するか」という特定のタスクに特化しています。

AirflowのPythonOperatorを使えば、PandasやPolarsライブラリを駆使して複雑なデータ変換を行うことも可能です。しかし、そのロジックはPythonスクリプトの中に閉じ込められ、SQLに習熟したアナリストからはブラックボックスに見えがちです。また、データのテストやドキュメンテーションも、Airflow単体ではdbtほど洗練された形では提供されません。

逆に、dbtはデータ変換の効率、信頼性、共同作業のしやすさを極限まで高めていますが、それ自体にはスケジューリング機能がありません(dbt Cloudには簡易的なスケジューラがありますが、複雑な依存関係の管理には不向きです)。また、データウェアハウスの外の世界、例えば「SaaS APIからデータを取ってくる」といった処理はdbtの守備範囲外です。

この根本的な思想の違いが、それぞれのツールのアーキテクチャや機能セットに反映されています。

詳細機能比較:Airflow vs dbt

両者の違いをより具体的に理解するために、いくつかの重要な観点から比較表を作成しました。データエンジニアとしてのツール選定や学習の優先順位付けに役立ててください。

観点 Apache Airflow dbt (Data Build Tool) 解説・考察
主要な目的 ワークフローのオーケストレーション データウェアハウス内でのデータ変換 Airflowは「いつ、何を」を管理する司令塔。dbtは「どう変換するか」を実行する専門家。役割が根本的に異なる。
主要言語 Python (DAG定義) SQL + Jinja (モデル定義) Pythonの知識が必須のAirflowに対し、dbtはSQLスキルがあれば始められる。アナリストにとっての参入障壁はdbtの方が低い。
スコープ End-to-End (システムを問わない) データウェアハウス/レイクハウス内に限定 AirflowはAPI、DB、Spark、ML基盤など何でも扱える。dbtはBigQuery, Snowflake, RedshiftなどのDWHが主戦場。
実行モデル タスクベース。Operatorが処理の単位。 モデルベース。SQLファイルが処理の単位。 Airflowは多様なOperatorを組み合わせる。dbtはSQLモデル間の依存関係をグラフとして実行する。
依存関係の定義 Pythonコードで明示的に定義 (>>, <<, set_upstream) ref()関数による暗黙的な定義 dbtのref()は非常に直感的で強力。コードから自動的に依存関係グラフ(リネージ)を構築できるのが強み。
開発者体験 (DX) 柔軟性が高いが、ローカルでのテストやデバッグに工夫が必要な場合がある。UIは運用監視に強い。 CLI中心で高速なフィードバックサイクル。プレビューやテストが容易。ドキュメントサイト生成は秀逸。 dbtは分析コードの開発サイクルを回すことに最適化されている。Airflowは本番環境での安定運用に重きを置いている。
テスト Pythonの単体テスト/結合テストでDAGの構造をテスト可能。データ自体のテストは自作が必要。 データ品質テストが第一級市民。スキーマテスト(not_null, uniqueなど)やカスタムデータテストが組み込み。 「変換後のデータが期待通りか」を保証する能力はdbtが圧倒的に優れている。データエンジニアリングにおける信頼性の要。
状態管理 専用のメタデータデータベースでタスクの実行状態などを厳密に管理。 基本的にはステートレス。実行結果はDWHにテーブル/ビューとして反映される。状態はDWHが持つ。 Airflowは「過去にどのタスクが成功/失敗したか」を覚えている。dbtは実行のたびにDWHの状態を正として変換を行う。
拡張性 Providers/Plugins機構により、多様な外部システムとの連携が可能。カスタムOperatorも作成可能。 Packages (ライブラリ) / Macros (関数) により、SQLロジックの再利用や拡張が可能。 Airflowの拡張性は「連携できるシステムの種類」を増やす方向。dbtの拡張性は「SQL変換ロジック」を豊かにする方向。
主な利用者 データエンジニア、DevOpsエンジニア、MLエンジニア アナリティクスエンジニア、データアナリスト、データエンジニア 利用者のペルソナが異なる点が面白い。dbtはアナリストとエンジニアの間のギャップを埋める役割を担っている。

コードで見る依存関係の定義の違い

両者のスタイルの違いをコードで見てみましょう。これは、上流の2つのテーブル(stg_users, stg_orders)をJOINして、顧客ごとの注文情報を持つ中間テーブル(int_user_orders)を作成する、という単純な依存関係です。

Airflow DAGの例

Airflowでは、各処理を「タスク」として定義し、それらの実行順序を>>のようなビットシフト演算子で明示します。


from airflow.models.dag import DAG
from airflow.providers.google.cloud.operators.bigquery import BigQueryExecuteQueryOperator
from datetime import datetime

with DAG(
    dag_id='user_orders_pipeline',
    start_date=datetime(2025, 1, 1),
    schedule_interval='@daily',
    catchup=False,
) as dag:
    # ユーザー情報をステージングするタスク
    task_stage_users = BigQueryExecuteQueryOperator(
        task_id='stage_users',
        sql='sql/staging/stg_users.sql',
        use_legacy_sql=False,
    )

    # 注文情報をステージングするタスク
    task_stage_orders = BigQueryExecuteQueryOperator(
        task_id='stage_orders',
        sql='sql/staging/stg_orders.sql',
        use_legacy_sql=False,
    )

    # ステージングされたテーブルをJOINするタスク
    task_intermediate_user_orders = BigQueryExecuteQueryOperator(
        task_id='intermediate_user_orders',
        sql='sql/intermediate/int_user_orders.sql',
        use_legacy_sql=False,
    )

    # 依存関係を定義
    [task_stage_users, task_stage_orders] >> task_intermediate_user_orders

dbtモデルの例

dbtでは、int_user_orders.sqlファイルの中でref()関数を使うだけで、依存関係がdbtによって自動的に解釈されます。


-- models/intermediate/int_user_orders.sql

-- dbtは以下のref()を解釈し、stg_usersとstg_ordersのモデルを
-- このモデルより先に実行する必要があることを自動で認識する。

SELECT
    u.user_id,
    u.name,
    o.order_id,
    o.order_date,
    o.amount
FROM
    {{ ref('stg_users') }} AS u
LEFT JOIN
    {{ ref('stg_orders') }} AS o
ON
    u.user_id = o.user_id

このように、dbtは変換ロジックの記述に集中できる一方、Airflowはパイプライン全体の制御をより細かく記述するスタイルであることがわかります。これがデータパイプライン開発における両者のアプローチの根本的な違いです。

ユースケース別に見る最適な選択

理論的な違いは分かりました。では、実際のプロジェクトではどちらを選べば良いのでしょうか?いくつかの典型的なシナリオを考えてみましょう。

シナリオ1:モダンなDWH中心のスタートアップ

  • 状況:データチームは数名。データソースはSalesforceやGoogle AnalyticsなどSaaSが中心。FivetranやStitchのようなELTツールでデータをSnowflakeに集約済み。主なタスクは、Snowflake内でデータを加工し、BIツール(Looker, Tableau)で可視化すること。
  • 推奨:dbtを最優先で導入する。
  • 理由:このシナリオのボトルネックは、DWHにロードされた生データをいかに迅速かつ信頼性高くビジネスインサイトに繋がる形に変換できるか、です。dbtはまさにこの課題を解決するために作られました。SQLが得意なアナリストでも、テストやバージョン管理の恩恵を受けながら開発に参加できます。dbt Cloudを使えば、簡易的なスケジューリングも可能で、インフラ管理の手間も省けます。まずはdbtで変換レイヤーを確立し、必要になったらAirflowを導入してdbtのジョブをキックする、というステップが現実的です。

シナリオ2:多様なデータソースと処理を持つ大企業

  • 状況:オンプレミスのOracle DB、Hadoopクラスター上のSparkバッチ、社内マイクロサービスからのAPI、AWS S3のファイルなど、データソースと処理が多岐にわたる。機械学習モデルの定期的な再学習とデプロイもパイプラインの一部。
  • 推奨:Airflowをオーケストレーションの核として採用する。
  • 理由:この複雑な環境では、dbtだけでは歯が立ちません。異なるシステム間の依存関係を管理し、パイプライン全体を俯瞰的に監視できるAirflowの能力が不可欠です。例えば、「Oracle DBからのデータ抽出が完了したら(OracleOperator)、S3にファイルを配置し(S3Hook)、それをトリガーにSparkジョブを実行し(SparkSubmitOperator)、その結果をBigQueryにロードし(GCSToBigQueryOperator)、ロード完了後にdbtジョブをキックする(BashOperator)」といった複雑なワークフローをエレガントに記述できます。

シナリオ3:データアナリストチームが主導する分析基盤改善

  • 状況:データエンジニアはいるが、日々の分析用データマートの作成はSQLに長けたアナリストたちが担当している。しかし、各自が書いた大量のSQLスクリプトがブラックボックス化し、依存関係が不明で、変更の影響範囲もわからない「秘伝のタレ」状態になっている。
  • 推奨:dbtを導入し、既存のSQLをリファクタリングする。
  • 理由:dbtは、このような混沌としたSQL資産を整理・構造化するための特効薬です。アナリストは使い慣れたSQLを書きながら、ref()で依存関係を明確にし、テストを記述し、ドキュメントを自動生成できます。これにより、属人化が解消され、チームでの共同開発が劇的に改善します。データエンジ...ニアは、dbtプロジェクトの基盤構築やCI/CDパイプラインの整備に注力することで、アナリストチーム全体の生産性を向上させることができます。

シナリオ4:MLOpsを含む機械学習パイプライン

  • 状況:単にデータを変換するだけでなく、特徴量エンジニアリング、モデルトレーニング、ハイパーパラメータチューニング、モデル評価、A/Bテスト用のモデルサービングまでを自動化したい。
  • 推奨:Airflow(またはKubeflow, Argo Workflowsのような類似ツール)が主役。dbtは特徴量生成のステップで貢献。
  • 理由:MLパイプラインは、Pythonのライブラリ(Scikit-learn, TensorFlow, PyTorch)やコンテナ技術(Docker, Kubernetes)との親和性が極めて重要です。PythonネイティブであるAirflowは、これらのタスクを自然に統合できます。KubernetesPodOperatorを使えば、各ステップを独立したコンテナとして実行でき、リソース管理や環境分離も容易です。このパイプラインの中で、「DWHから学習データを抽出し、特徴量を作成する」という前処理の部分をdbtに担当させることで、再現性の高い特徴量ストアを構築できます。

Airflowとdbtの共存:最強のデータパイプラインを構築する

これまでのシナリオで明らかなように、多くの現代的なデータチームにとっての最適解は「Airflow vs dbt」ではなく、「Airflow and dbt」です。両者を組み合わせることで、それぞれの長所を最大限に活かした、堅牢でスケーラブルなデータパイプラインを構築できます。

一般的な連携パターン:

  1. E (Extract) & L (Load): Airflowが様々なデータソースからデータを抽出し、データウェアハウスにロードする。これはAirflowの得意分野。
  2. T (Transform): ロードが完了したことをトリガーに、Airflowがdbtのコマンドライン(dbt run, dbt test)を実行するタスクをキックする。
  3. Downstream Tasks: dbtによる変換が成功したら、Airflowが後続のタスク(BIツールのキャッシュ更新、Slackへの完了通知、逆ETL処理など)を実行する。

このアーキテクチャでは、Airflowがパイプライン全体の指揮者として、DWHの外の世界を含めたタスクの実行順序とスケジュールを管理します。一方、dbtはDWH内部の変換処理の専門家として、複雑なビジネスロジックをSQLで実装し、その品質とドキュメンテーションを担保します。この役割分担こそが、モダンデータスタックにおけるベストプラクティスとされています。

AirflowのDAG内でdbtを実行するタスクは、通常BashOperatorを使って以下のようにシンプルに記述できます。


from airflow.operators.bash import BashOperator

# dbtプロジェクトのディレクトリに移動してdbt runを実行
run_dbt_models = BashOperator(
    task_id='run_dbt_models',
    bash_command='cd /path/to/your/dbt/project && dbt run --models tag:daily',
)

# dbtのテストを実行
test_dbt_models = BashOperator(
    task_id='test_dbt_models',
    bash_command='cd /path/to/your/dbt/project && dbt test',
)

# 実行順序を定義
# ... (Extract/Loadタスク) >> run_dbt_models >> test_dbt_models >> ... (後続タスク)

近年では、Astronomer社が提供するCosmosのようなツールも登場しており、dbtの各モデルをAirflowの独立したタスクとして可視化・実行できるようになり、両者の連携はさらにシームレスになっています。

結論:データエンジニアとしてのあなたの選択

さて、長い旅を経て、最初の問いに戻りましょう。「Apache Airflowとdbt、結局どっちを選ぶべきか?」

答えは、あなたがどのようなデータエンジニアを目指し、どのような課題を解決したいかによって決まります。

Airflowを学ぶべき人:

  • システムの境界を越えて、エンドツーエンドのデータパイプライン全体を設計・運用したい方。
  • Pythonを使ったプログラミングが好きで、データ処理だけでなく、インフラやMLOpsなど幅広い領域に興味がある方。
  • 複雑な依存関係やスケジューリング、エラーハンドリングをロバストに実装する「オーケストレーション」の技術を深く学びたい方。

Airflowは、データエンジニアリングの「汎用性」と「基盤力」を象徴するツールです。

dbtを学ぶべき人:

  • データの本質的な価値、つまり「ビジネスに意味のある情報」を生み出すデータモデリングと変換処理に情熱を注ぎたい方。
  • SQLを武器に、データの品質、信頼性、再利用性を高めることに喜びを感じる方。
  • データアナリストとエンジニアの架け橋となる「アナリティクスエンジニア」としてのキャリアパスに興味がある方。

dbtは、データエンジニアリングの「専門性」と「品質」を象徴するツールです。

理想を言えば、現代の優れたデータエンジニアは、両方のツールを理解し、その哲学を尊重し、プロジェクトの状況に応じて適切に使い分ける、あるいは組み合わせて使う能力を持っています。あなたのデータエンジニアリング ロードマップにおいて、この二つのツールは避けては通れない重要なマイルストーンです。

もしあなたがキャリアの初期段階にいるなら、まずはdbtから始めて、高品質なデータ変換のプラクティスを身につけるのも良い戦略です。SQLという馴染み深い言語で、テストやドキュメンテーションといったエンジニアリングの基礎を学べます。そして、より複雑なパイプラインの必要性に迫られたとき、Airflowを学び始めることで、dbtで培った知識がさらに活きてくるでしょう。

Airflowとdbtは、競合するツールではなく、互いを補完し合う最高のパートナーです。この二つの強力なツールをマスターすることで、あなたのデータエンジニアとしての市場価値は飛躍的に高まるはずです。さあ、まずはどちらかのドキュメントを開いて、小さなプロジェクトから始めてみませんか?

Post a Comment