🧶

dbt Core でもマルチプロジェクト!dbt-loom × Databricks で実現するグループ横断データ基盤

に公開

はじめに

弊社では M&A によるグループ会社の増加に伴い、取り扱うデータや組織が急拡大しています。
それに伴い、データ基盤においても「複数のグループ会社(プロジェクト)のデータをどう管理するか」という課題に直面しました。

当初は単一の dbt プロジェクトで全社のデータを管理していましたが、以下の限界が見えてきました。

  • 権限管理の複雑化: グループ会社ごとに閲覧できるデータを制御したいが、1 つのプロジェクトだと設定が煩雑になる。

  • 障害影響範囲(Blast Radius)の拡大リスク: 将来的にグループ会社数が増えた際、1 つの設定ミスが全グループ会社のパイプラインを停止させるリスクを未然に防ぎたい(防火壁を作りたい)。

そこで、「グループ会社ごとに dbt プロジェクトを分割し、分析時は横断的にデータを参照できる基盤」 を構築することにしました。

通常、dbt でマルチプロジェクト構成(dbt Mesh)を実現するには dbt Cloud Enterprise 版が必要ですが、今回はコストを抑えつつ同様の機能を実現するため、OSS の dbt-loom を採用しました。

本記事では、Databricks 環境上で dbt Core + dbt-loom を用いて、実用的なマルチプロジェクト基盤を構築した事例を紹介します。

想定読者

  • dbt Core を利用しており、マルチプロジェクト構成(dbt Mesh)に興味がある方
  • Databricks 上で dbt を運用している、または検討している方
  • 組織の拡大に伴い、dbt プロジェクトの肥大化やガバナンスに課題を感じている方

※本記事は、導入初期の 「アーキテクチャ設計」 に焦点を当てた事例紹介です。将来的な組織・データ規模の拡大(数倍〜数十倍)を見据えた技術選定の意図を中心に解説します。

アーキテクチャ:グループ会社別プロジェクトを繋ぐ

  • プロジェクト分割: グループ会社単位で dbt プロジェクトを作成(例: company_a, company_b)。これらは独立して開発・運用されます。

  • 横断分析プロジェクト: グループ全体の分析を行うためのプロジェクト(main_project)を用意。

  • dbt-loom による連携: main_project から、company_acompany_b のモデルを {{ ref() }} で直接参照。

なお、リポジトリ自体は 1 つに統合(モノレポ)しています。

なぜ {{ source }} ではなく dbt-loom なのか?

他プロジェクトのテーブルを参照するだけなら、{{ source('company_a', 'table_name') }} のように Source として定義する方法もあります。しかし、以下の理由から dbt-loom を採用しました。

  1. リネージの維持: Source 参照だとリネージがそこで途切れてしまいますが、dbt-loom ならプロジェクトを跨いでリネージが繋がります。これにより、上流(各グループ会社)の変更が下流(横断分析)にどう影響するかを追跡できます。
  2. 開発体験の統一: 自プロジェクトのモデルと同じ感覚で {{ ref() }} を使えるため、開発者が「これは他プロジェクトのテーブルだから...」と意識するコストが下がります。

プロジェクト分割のメリット:権限管理の簡素化

プロジェクトを物理的に分割したことで、権限管理の設計 も大幅にシンプルになりました。

以前は単一プロジェクト内で、マクロを駆使してモデル単位(テーブル単位)で権限を制御する必要があり、管理が非常に煩雑でした。
今回の構成では、各プロジェクトを Databricks の独立した単位として管理することで、Unity Catalog を用いてプロジェクト単位で権限を設定できるようになりました。
これにより、セキュリティ設計の見通しが良くなり、運用コストも下がると見込んでいます。

実装のポイント:Databricks Volume の活用

dbt-loom は、他プロジェクトのアーティファクト(manifest.json)を読み込むことで、そのプロジェクトのモデル情報を取得します。
AWS S3 や GCS を使うのが一般的ですが、今回は Databricks Volume をアーティファクト置き場として利用しました。

理由:運用コストの最小化

最大の理由は、dbt の実行基盤として Databricks Jobs を利用している点にあります。
Jobs の実行環境には Databricks Volume を直接マウントできるため、dbt build の成果物である manifest.json をそのまま Volume に出力するだけで、他プロジェクトへの共有が完了します。

もし S3 や GCS を使う場合、認証情報の管理やアップロード用のスクリプトを別途メンテナンスする必要がありますが、この構成なら追加のインフラ管理やコード記述が一切不要になります。この「シンプルさ」こそが、Databricks Volume を採用した決定的な理由です。

実装:シンプルな設定

dbt-loom の導入に、複雑なコードやインフラ構築は必要ありません。
「参照される側で公開設定」「参照する側でマニフェスト指定」 、そして 「モデルからの参照」 の 3 ステップで完了します。

1. 参照される側(各グループ会社)
モデルの定義ファイルに access: public を追記するだけです。

# models/schema.yml
version: 2

models:
  - name: stg_service_a__users
    access: public # これだけで他プロジェクトから見えるようになる

2. 参照する側(横断分析プロジェクト)
設定ファイル(dbt_loom.config.yml)に、Databricks Volume 上のマニフェストのパスを書くだけです。

# dbt_loom.config.yml
manifests:
  - name: company_a_project
    type: databricks
    config:
      path: /Volumes/dbt_artifact/artifacts/company_a/manifest.json

3. モデルの参照方法
あとは通常の ref 関数にプロジェクト名の引数を追加するだけです。

select * from {{ ref('company_a_project', 'stg_service_a__users') }}

たったこれだけの記述で、異なるプロジェクト間の連携が実現できます。

課題と解決:OSS へのコントリビュート

導入にあたり、dbt-loom が Databricks 上のパス(Workspace, DBFS, Volumes など)を正しく解釈できず、API リクエストが失敗するという問題に直面しました。

実は、私にとってこれが 人生初の OSS コントリビュート でした。
それでも、「このアーキテクチャを実現するには dbt-loom が絶対に必要だ」という確信があったため、コードを読み解き、dbt-loom 本体への修正パッチ(Pull Request)を作成しました。

結果として無事にマージされ、Databricks の様々なパス形式に対応できるようになりました。

具体的には、パスのパース処理を修正し、Workspace パスや DBFS パスなど、それぞれの形式に応じた適切な Databricks API を呼び出すように改善しました。
これにより、Databricks Volume 上の manifest も問題なく読み込めるようになりました。

実践:グループ横断でのモデル作成

この基盤を構築したことで、グループ会社を跨いだデータモデルの作成 が非常にスムーズになりました。

例えば、グループ共通の顧客 ID(共通 ID)と、各グループ会社のアプリ会員 ID を紐付けるマッピングテーブルなど、複数のプロジェクトに分散しているデータを結合する必要があるケースでも、あたかも同じプロジェクトにあるかのように {{ ref() }} で参照できています。

これにより、リネージを途切れさせることなく、グループ全体を俯瞰した分析が可能になりました。

まとめ

dbt-loom と Databricks を組み合わせることで、以下の成果が得られました。

  • 組織のスケーラビリティ: グループ会社ごとにプロジェクトを分割し、権限やドキュメントを適切に分離できた。
  • データの結合性: プロジェクトは分かれていても、リネージを繋げて横断的な分析(ID 統合など)がスムーズに行えるようになった。
  • コスト最適化: Enterprise 版の機能を、OSS と工夫で実現できた。

M&A などで組織が複雑化していくフェーズで同じような課題をお持ちの方に、この「分割しつつ繋ぐ」アーキテクチャが選択肢の 1 つとして参考になれば幸いです。

Discussion