🦄

DuckDBでdbt

2025/02/11に公開

TL;DR

DuckDBとdbtでモデリングのサンプル作成して検証しました。
主な目的はPandasとdbtモデリングのそれぞれで使い分けるべき場面を見極めたい。

得意分野

まず、dbtとPandasの得意分野を比較。
モジュール化&再利用性など運用効率を考慮した時に差が出そうです。

Aspect dbt の特徴 Pandas の特徴
スケーラビリティ SQL を用いてデータウェアハウス上で直接処理するため、大規模データの変換・処理が可能。 メモリ内で処理するため、大規模データの場合にパフォーマンスやメモリ制約が発生。
モジュール化 & 再利用性 SQL モデルとして変換ロジックを分割し、依存関係を明示的に管理できる。Jinja テンプレートを利用したコードの再利用性も高い。 スクリプトベースで記述するため、コードの分割や依存関係管理は手動で行う必要があり、保守性は低め。
テスト & ドキュメント生成 組み込みのテスト機能(not_nullunique など)があり、また dbt docs generate でモデル間の依存関係(DAG)を自動生成できる。 テストフレームワークやドキュメント生成機能は標準で備わっておらず、別途実装が必要。
バージョン管理 & チーム開発 SQL/YAML ファイルとして管理されるため、Git などのバージョン管理ツールや CI/CD パイプラインとの連携が容易。 Python スクリプトとして管理されるが、データパイプライン全体の変更管理や依存関係の把握はやや困難。
プロダクション運用 バッチ処理や自動テスト、エラーハンドリングなど、プロダクション向けのデータ変換パイプラインの構築に適している。 主にデータ探索やアドホックな分析に向いており、プロダクション運用を想定した機能は限定的。
BIツール連動 そもそもDBを保持しているので連動は容易。 連動するためには別途DBなどを容易する必要がある。

dbtのメリット

SQLコードのバージョン管理と共有:

SQLでデータ変換ロジックを記述するため、Gitなどのバージョン管理システムを通じて、コードの変更履歴やコラボレーションが容易になります。

モデル間の依存関係の自動管理:

各SQLモデル(変換ロジック)の依存関係を明示的に定義でき、dbtが自動で依存関係グラフを生成・管理します。これにより、パイプライン全体の流れを把握しやすくなります。

データ品質テストの自動化:

組み込みのテスト機能(not_null、unique、カスタムテストなど)を利用して、変換後のデータ品質を自動的に検証し、問題を早期に発見できます。

自動ドキュメント生成:

dbtは、モデルの依存関係や変換ロジックをもとに、ドキュメントとデータラインエージを自動生成します。これにより、チーム全体でデータパイプラインの理解が深まります。

再利用性と一貫性の向上:

Jinjaテンプレートやマクロを用いることで、共通のロジックやコードを再利用でき、変換ルールの一貫性を保ちながら開発効率を向上させます。

CI/CDパイプラインとの統合:

dbtは、Gitと連携してCI/CD環境での自動テスト・デプロイが可能なため、変更があった際の迅速な反映や品質管理が実現できます。

スケーラブルなデータパイプラインの構築:

データウェアハウス上で直接変換を実行するため、大規模データに対しても高いパフォーマンスで処理を行うことができます。

透明性と監査性の向上:

すべての変換ロジックがコードとして管理されるため、誰がいつどのような変更を加えたかを追跡しやすく、監査対応も容易です。

データカタログ:

自動生成されたドキュメントは、データカタログとして利用でき、利用者がデータの内容や変換ロジック、品質基準を容易に参照できる環境を提供します。

dbtの操作方法

Seed

$ dbt seed
07:56:16  Running with dbt=1.9.2
07:56:16  Registered adapter: duckdb=1.9.1
07:56:16  Found 5 models, 4 seeds, 426 macros
07:56:16  
07:56:16  Concurrency: 1 threads (target='dev')
07:56:16  
07:56:16  1 of 4 START seed file main.customers .......................................... [RUN]
07:56:17  1 of 4 OK loaded seed file main.customers ...................................... [INSERT 3 in 0.05s]
07:56:17  2 of 4 START seed file main.dates .............................................. [RUN]
07:56:17  2 of 4 OK loaded seed file main.dates .......................................... [INSERT 3 in 0.02s]
07:56:17  3 of 4 START seed file main.products ........................................... [RUN]
07:56:17  3 of 4 OK loaded seed file main.products ....................................... [INSERT 3 in 0.02s]
07:56:17  4 of 4 START seed file main.sales .............................................. [RUN]
07:56:17  4 of 4 OK loaded seed file main.sales .......................................... [INSERT 3 in 0.02s]
07:56:17  
07:56:17  Finished running 4 seeds in 0 hours 0 minutes and 0.27 seconds (0.27s).
07:56:17  
07:56:17  Completed successfully
07:56:17  
07:56:17  Done. PASS=4 WARN=0 ERROR=0 SKIP=0 TOTAL=4

Run

$ dbt run
07:57:14  Running with dbt=1.9.2
07:57:15  Registered adapter: duckdb=1.9.1
07:57:15  Found 5 models, 4 seeds, 426 macros
07:57:15  
07:57:15  Concurrency: 1 threads (target='dev')
07:57:15  
07:57:15  1 of 5 START sql view model main.dim_customers ................................. [RUN]
07:57:15  1 of 5 OK created sql view model main.dim_customers ............................ [OK in 0.06s]
07:57:15  2 of 5 START sql view model main.dim_dates ..................................... [RUN]
07:57:15  2 of 5 OK created sql view model main.dim_dates ................................ [OK in 0.03s]
07:57:15  3 of 5 START sql view model main.dim_products .................................. [RUN]
07:57:15  3 of 5 OK created sql view model main.dim_products ............................. [OK in 0.14s]
07:57:15  4 of 5 START sql view model main.fact_sales .................................... [RUN]
07:57:15  4 of 5 OK created sql view model main.fact_sales ............................... [OK in 0.03s]
07:57:15  5 of 5 START sql view model main.star_schema_view .............................. [RUN]
07:57:15  5 of 5 OK created sql view model main.star_schema_view ......................... [OK in 0.03s]
07:57:15  
07:57:15  Finished running 5 view models in 0 hours 0 minutes and 0.48 seconds (0.48s).
07:57:15  
07:57:15  Completed successfully
07:57:15  
07:57:15  Done. PASS=5 WARN=0 ERROR=0 SKIP=0 TOTAL=5

DBデータ確認

import duckdb
import pandas as pd

# DuckDB データベースファイルに接続
con = duckdb.connect('duckdb.db')

# star_schema_view テーブルの先頭 10 行を DataFrame として取得
df = con.execute('SELECT * FROM star_schema_view LIMIT 10').df()

# DataFrame を表示
df

Document

以下コマンドでドキュメント作成できます。モデル間の関係性を確認する事が可能です。

$ dbt docs generate

https://tkc.github.io/duckdb-dbt/#!/model/model.my_star_schema_project.star_schema_view

Modeling

Modelingはスターを採用、各モデルの依存関係がより明確になり再利用性が高まります。
以下のように定義しています。

  • dim(ディメンション): 製品、顧客、日付など、背景となる説明的な情報を保持するテーブル。
  • fact(ファクト): 売上や取引など、実際の事象の数値データやメトリクスを保持するテーブル。
  • star(スタースキーマ): 中心にファクトテーブルを持ち、その周囲に複数のディメンションテーブルを配置するデータモデリング手法。これにより、データの集計や分析が容易になります。

Dim(ディメンションテーブル)

意味・役割

ディメンションテーブルは、ファクトテーブルで記録される数値的な事象(測定値)の背景にある「属性情報」や「説明情報」を保持します。
具体的には、顧客、製品、日付、地域などの情報がこれにあたります。

特徴

背景情報の提供
ファクトテーブルの数値データに対して、より詳細な属性情報を付加し、データの意味を理解しやすくします。

説明的な情報を保持

例:顧客の名前や住所、製品のカテゴリーや価格帯、日付に関する詳細情報など。

クエリでのフィルタリングに利用

レポート作成時や分析時に、特定の属性(例:特定の地域、特定の期間)でデータを絞り込むための条件として利用されます。

  • dim_customers
  • 顧客ID、顧客名、住所、地域など
  • dim_products
  • 製品ID、製品名、カテゴリー、価格帯など
  • dim_dates
  • 日付、年、月、四半期など

Fact(ファクトテーブル)

意味・役割

ファクトテーブルは、実際の事象や取引の数値データ(測定値)を記録するテーブルです。
売上や数量、利益、コストなどの集計値を保持し、ビジネスのパフォーマンスを評価するための基礎データとなります。

特徴

数値的な測定値を格納
売上金額、数量、利益などの数値データが中心となります。

外部キーの活用
各レコードは、ディメンションテーブルのキー(例:顧客ID、製品ID、日付キー)を参照することで、背景情報と紐づけられています。

集計や分析の中心
ビジネス分析やレポート作成時に、主にこのファクトテーブルが利用され、さまざまな指標の集計や統計解析が行われます。

  • fact_sales
  • 各売上取引において、どの顧客がどの製品を、どの日にどれだけ購入したか(数量、金額など)を記録

Star(スタースキーマ)

意味・役割

スタースキーマは、データモデリングの設計パターンの一つで、中心にファクトテーブルを配置し、その周囲に複数のディメンションテーブルを配置することで「星形(スター)」のような構造を実現します。

特徴

シンプルな構造。ファクトテーブルを中心とし、ディメンションテーブルが放射状に配置されるため、全体像が直感的に把握しやすい。

パフォーマンスの向上

JOIN の数が比較的少なく、クエリがシンプルになるため、分析処理が高速に行えます。

使いやすい分析環境

データのスライス&ダイス(切り口ごとの集計や分析)が容易になり、BI ツールとの連携もスムーズです。

repo
https://github.com/tkc/duckdb-dbt

参考

https://zenn.dev/dbt_tokyo/books/537de43829f3a0

Discussion