Ritolabo
  1. Home
  2. GoogleCloud
  3. Dataform
  4. Dataform の開発ワークスペースで SQLX を使った開発を行う

Dataform の開発ワークスペースで SQLX を使った開発を行う

  • 公開日
  • カテゴリDataform
  • タグDataform,BigQuery
Dataform の開発ワークスペースで SQLX を使った開発を行う

前回の記事では、Terraform を使って Dataform のインフラ(リポジトリ・サービスアカウント・リリース設定・ワークフロー設定)を構築した。Terraform が作る「箱」の中で、実際に SQLX コードを書いて開発するのが本記事の内容。

開発ワークスペースの作成から、SQLX ファイルの記述、ワークフローの実行、Git 連携までを順に解説する。

contents

  1. 前提
  2. 開発ワークスペース
    1. ワークスペースとは
    2. ワークスペースの運用
    3. ワークスペースの作成
    4. ワークスペースの初期化
  3. workflow_settings.yaml
  4. SQLX ファイルの作成
    1. ディレクトリ構造
    2. config ブロック
    3. ソースの宣言(declaration)
    4. ref() による依存関係
    5. テーブルの作成(table)
  5. ワークフローの実行
    1. 開発ワークスペースからの実行
    2. 実行結果の確認
  6. Git 連携
    1. commit & push
    2. PR → merge

前提

  • Dataform リポジトリが作成済み(Terraform or UI)
  • GitHub リポジトリと連携済み
  • サンプルデータとして dl_sample データセットに以下の4テーブルが存在する
テーブル内容
usersユーザー
products商品
orders注文
order_items注文明細

本記事で作成するテーブルの構成は以下の通り。

dl_sample(既存)
    ↓
dwh_sample.order_summary     (注文サマリー)
dwh_sample.product_sales     (商品別売上)
    ↓
dm_sample.daily_sales_report (日次売上レポート)

開発ワークスペース

ワークスペースとは

開発ワークスペースは、Dataform リポジトリ内の作業環境。Git ブランチと対応しており、各開発者が独立して SQLX の編集・実行・テストを行える。

Dataform リポジトリ
├── 開発ワークスペース A(feature-A ブランチ)
├── 開発ワークスペース B(feature-B ブランチ)
└── メインブランチ(本番デプロイ対象)

作業完了後は PR を経てメインブランチにマージし、本番環境にデプロイする。

ワークスペースの運用

公式ドキュメントでは 開発者1人につき1ワークスペース を作成する運用が推奨されている。ワークスペース名には開発者名を使う。

Dataform リポジトリ
├── rito(rito の開発ワークスペース)
├── sasha(sasha の開発ワークスペース)
└── main ブランチ(本番デプロイ対象)

この運用が推奨される理由は ${workspaceName} 変数の仕組みにある。ワークスペースコンパイルオーバーライドでスキーマサフィックスに ${workspaceName} を指定すると、開発者ごとに BigQuery スキーマが自動分離される。

ワークスペース: rito  → dwh_sample_rito, dm_sample_rito
ワークスペース: sasha → dwh_sample_sasha, dm_sample_sasha
本番(リリース構成)  → dwh_sample, dm_sample

これにより各開発者が独立したスキーマで作業でき、他の開発者のテーブルを誤って上書きするリスクがなくなる。

項目内容
粒度開発者1人に1ワークスペース
命名開発者名(例: rito
使用文字英数字、ハイフン、アンダースコアのみ
維持コストなし(不要になったら削除可)
注意ワークスペース削除後も BigQuery 側の開発スキーマは手動削除が必要

参考:

ワークスペースの作成

Dataform リポジトリ画面で「開発ワークスペースを作成」をクリックする。

リポジトリ画面で「開発ワークスペースを作成」

ワークスペース ID に開発者名(例: rito)を入力して作成する。

ワークスペースID入力ダイアログ
作成された開発ワークスペース

ワークスペースの初期化

新規作成直後のワークスペースは空の状態。「初期化」を実行すると、以下のファイルが自動生成される。

ワークスペース初期化ボタン
初期化後のファイル一覧
definitions/
├── first_view.sqlx       # サンプルファイル(削除可)
└── second_view.sqlx      # サンプルファイル(削除可)
includes/                  # 共通関数・変数を定義
.gitignore
workflow_settings.yaml     # プロジェクト設定

definitions/ 配下のサンプルファイルは不要なため削除して構わない。

workflow_settings.yaml

ワークスペースの初期化で自動生成される設定ファイル。Dataform プロジェクトの基本情報を定義する。

自動生成時の内容:

defaultProject: <YOUR-PROJECT-ID>
defaultDataset: dataform
defaultAssertionDataset: dataform_assertions
dataformCoreVersion: 3.0.37

設定可能な全項目は以下の通り。

項目説明デフォルト値
defaultProject出力先の GCP プロジェクト ID
defaultDatasetデフォルトの出力先データセット。config で schema を省略した場合に使われるdataform
defaultLocationBigQuery のリージョン(省略可)
defaultAssertionDatasetassertion(データ品質テスト)結果のビューを格納するデータセットdataform_assertions
dataformCoreVersionDataform コアライブラリのバージョン
datasetSuffix全データセット名に追加するサフィックス。開発/本番の分離に使う(省略可)
projectSuffix全プロジェクト参照に追加するサフィックス(省略可)
namePrefix全テーブル名に追加するプレフィックス(省略可)
varsコンパイル時に使えるユーザー定義変数(key-value)(省略可)
defaultIcebergConfigBigLake Iceberg テーブルのデフォルト設定(省略可)

defaultDataset はデフォルト値で、各 SQLX ファイルの config ブロックで schema を指定すれば個別にオーバーライドできる。今回のように出力先データセットを dwh_sampledm_sample と明示指定する構成では、defaultDataset の値は使われない。

参考: リポジトリを管理する

今回は、以下の設定で記載する。

defaultProject: <YOUR-PROJECT-ID>
defaultDataset: dataform
defaultAssertionDataset: dataform_assertions

SQLX ファイルの作成

ディレクトリ構造

definitions/ 配下にデータセット単位でディレクトリを整理する。

definitions/
├── dl_sample/        # ソース宣言(既存テーブル)
├── dwh_sample/       # DWH層
└── dm_sample/        # DM層

ディレクトリ名は整理のための論理的な分類に過ぎない。テーブルの出力先データセットは config ブロックの schema で決まる。今回は、データセットで分けている。

config ブロック

SQLX ファイルは config { ... } ブロックと SQL で構成される。config ブロックの type でファイルの役割を指定する。

type説明用途
tableテーブルを作成DWH/DM 層のテーブル
viewビューを作成軽量な参照用
incremental差分更新テーブル大量データの効率的な更新
declaration既存テーブルの宣言ソーステーブルの登録
operations任意の SQL を実行DDL、DML、プロシージャ呼び出し等
assertionデータ品質テストバリデーション

config ブロックでは type の他に以下の項目を設定できる。

項目説明
schema出力先データセット名
nameテーブル名(省略時はファイル名)
descriptionテーブルの説明(BigQuery のメタデータに反映)
columnsカラムごとの説明(BigQuery のメタデータに反映)

ソースの宣言(declaration)

Dataform で管理していない(Data Transfer Service で作成されたテーブルなど)既存テーブルを「ソース」として登録する。今回は dl_sample のテーブル群が該当する。

definitions/dl_sample/orders.sqlx:

config {
  type: "declaration",
  database: "<YOUR-PROJECT-ID>",
  schema: "dl_sample",
  name: "orders"
}
項目説明
typedeclaration = 既存テーブルの宣言
databaseGCP プロジェクト ID
schemaBigQuery データセット名
nameテーブル名

同様に usersproductsorder_items も宣言する。

definitions/dl_sample/users.sqlx:

config {
  type: "declaration",
  database: "<YOUR-PROJECT-ID>",
  schema: "dl_sample",
  name: "users"
}

definitions/dl_sample/products.sqlx:

config {
  type: "declaration",
  database: "<YOUR-PROJECT-ID>",
  schema: "dl_sample",
  name: "products"
}

definitions/dl_sample/order_items.sqlx:

config {
  type: "declaration",
  database: "<YOUR-PROJECT-ID>",
  schema: "dl_sample",
  name: "order_items"
}

宣言のメリット

宣言すると依存関係グラフにソーステーブルが表示され、データリネージが可視化される。ref() での参照も可能になる。

宣言なし                        宣言あり
─────────                       ─────────
依存関係グラフに                 依存関係グラフに
dl_sample.orders が             dl_sample.orders が
表示されない                    表示される
                                    │
                                    ↓
                               order_summary

宣言しなくても動く

宣言は必須ではない。FROM 句で直接テーブル名を指定すれば動作する。

-- 宣言なしでも直接参照可能
FROM dl_sample.orders

-- 宣言ありなら ref() で参照可能
FROM ${ref("orders")}

データの流れを可視化したい場合に宣言を使う。

ref() による依存関係

${ref("テーブル名")} を使うと、Dataform が依存関係を自動検出し、実行順序を制御する。declaration で宣言したソーステーブルも、type: "table" で作成するテーブルも、同じ ref() で参照できる。

-- ref() の書き方
FROM ${ref("orders")}          -- declaration で宣言したテーブル
FROM ${ref("order_summary")}   -- type: "table" で作成するテーブル

ref() で参照すると、参照先のテーブルが先に作成(または存在確認)されてから、参照元が実行される。

テーブルの作成(table)

order_summary

注文サマリーテーブルを作成する。

definitions/dwh_sample/order_summary.sqlx:

config {
    type: "table",
    schema: "dwh_sample",
    description: "注文サマリー:ユーザー別・注文別の合計金額",
    columns: {
        order_id: "注文ID",
        user_id: "ユーザーID",
        user_name: "ユーザー名",
        ordered_at: "注文日時",
        total_amount: "合計金額"
    }
}

SELECT
    o.order_id,
    o.user_id,
    u.name AS user_name,
    o.ordered_at,
    SUM(oi.quantity * oi.unit_price) AS total_amount
FROM
    ${ref("orders")} o
        JOIN
    ${ref("users")} u
    ON
        o.user_id = u.user_id
        JOIN
    ${ref("order_items")} oi
    ON
        o.order_id = oi.order_id
GROUP BY
    1,
    2,
    3,
    4

config ブロックの descriptioncolumns で設定したメタデータは、BigQuery テーブルの説明として反映される。テーブルの説明やカラムの意味をコードで管理できるのが Dataform の利点。

SQLX ファイル作成後、エディタ上部の「実行」でクエリの動作確認ができる。

クエリ実行結果の確認

product_sales

商品別売上サマリーテーブルを作成する。

definitions/dwh_sample/product_sales.sqlx:

config {
    type: "table",
    schema: "dwh_sample",
    description: "商品別売上サマリー",
    columns: {
        product_id: "商品ID",
        product_name: "商品名",
        category: "カテゴリ",
        total_quantity: "総販売数",
        total_sales: "総売上金額"
    }
}

SELECT
    p.product_id,
    p.name AS product_name,
    p.category,
    SUM(oi.quantity) AS total_quantity,
    SUM(oi.quantity * oi.unit_price) AS total_sales
FROM
    ${ref("products")} p
        JOIN
    ${ref("order_items")} oi
    ON
        p.product_id = oi.product_id
GROUP BY
    1,
    2,
    3

daily_sales_report

日次売上レポートテーブルを作成する。

definitions/dm_sample/daily_sales_report.sqlx:

config {
    type: "table",
    schema: "dm_sample",
    description: "日次売上レポート:注文サマリーと商品売上を結合",
    columns: {
        order_date: "注文日",
        total_orders: "注文数",
        total_revenue: "総売上",
        top_category: "売上トップカテゴリ"
    }
}

SELECT
    DATE(os.ordered_at) AS order_date,
    COUNT(DISTINCT os.order_id) AS total_orders,
    SUM(os.total_amount) AS total_revenue,
    (
    SELECT
    ps.category
    FROM
    ${ref("product_sales")} ps
    ORDER BY
    ps.total_sales DESC
    LIMIT
    1 ) AS top_category
FROM
    ${ref("order_summary")} os
GROUP BY
    1

依存関係グラフの確認

全テーブルを ref() で参照しているため、依存関係グラフに dl_sample → dwh_sample → dm_sample の流れが表示される。「COMPILED GRAPH」タブで確認できる。

依存関係グラフ(COMPILED GRAPH)

ワークフローの実行

開発ワークスペースからの実行

開発ワークスペースの「Start execution」から「All actions」を選択し、全テーブルを一括で作成する。

Start execution ボタン
All actions 選択画面

依存関係に従って order_summaryproduct_salesdaily_sales_report の順で実行される。

実行結果の確認

実行完了後、各アクションのステータスが表示される。全て成功していれば、BigQuery 上にテーブルが作成されている。

実行結果(全アクション成功)

Git 連携

commit & push

開発ワークスペースで作成した SQLX ファイルを GitHub に push する。

ワークスペース左上の変更ファイル一覧から、変更をステージングし、コミットメッセージを入力して「Push to remote branch」を実行する。

変更のステージングとコミット
Push to remote branch

PR → merge

push 後、ワークスペース左上に「Open repository to create PR」リンクが表示される。クリックすると GitHub の PR 作成画面に遷移する。

Open repository to create PR リンク

GitHub 上でレビュー後に main ブランチへマージすると、リリース設定のスケジュール(またはリリースの手動作成)により本番環境にデプロイされる。

まとめ

  • SQLX は config ブロック + SQL のシンプルな構造
  • ref() で依存関係を定義すれば、実行順序は Dataform が自動制御する
  • descriptioncolumns でメタデータもコードとして管理できる
  • 開発ワークスペースで動作確認し、Git 経由で本番に反映するフローが標準
  • 前回記事の Terraform 環境と組み合わせることで、インフラからコードまで再現性のある開発フローが実現できる

Author

rito

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級