[新機能]dbt Projects on Snowflakeで同一プロジェクトオブジェクトに対してdbtコマンドの並列実行が可能となりました

[新機能]dbt Projects on Snowflakeで同一プロジェクトオブジェクトに対してdbtコマンドの並列実行が可能となりました

dbt Projects on Snowflakeの新機能**並行実行機能**を試してみました。これまで複数の実行を同時に走らせるにはdbt project objectを複製する必要がありましたが、今回のアップデートで1つのプロジェクトをデプロイしたまま複数のコマンドを並列実行できるようになります。その仕組みと実装パターンを紹介します。
2026.09.11

さがらです。

dbt Projects on Snowflakeの新機能として、Slim CIとdefer to productionが一般提供(GA)されました。このアップデートには複数の機能が含まれていますが、その中の1つに、同一のdbt project objectを並列実行できる機能があります。

https://docs.snowflake.com/en/release-notes/2026/other/2026-09-10-dbt-artifacts-slim-ci-defer-to-production-ga

https://docs.snowflake.com/en/user-guide/data-engineering/dbt-projects-on-snowflake-slim-ci-defer-to-prod

これまでは、同一のdbt project objectに対して複数の実行を同時に走らせることができず、並列で実行したいモデル群がある場合はdbt project object自体を複製する構成になりがちでした。今回のアップデートで、1つのdbt project objectをデプロイしたまま、dbt buildなどのコマンドを複数かつ並列に実行できるようになったので、実際に試してみました。

機能概要

今回のGAで一般提供された機能は、大きく分けて以下の4つです。

  1. Slim CI: 最新の本番実行のdbtアーティファクト(manifest.jsonなど)をインポートし、変更されたリソースとその下流依存関係のみを検証する
  2. Defer to production: 未構築の上流参照を、既存の本番リレーションに解決する
  3. 並行実行: 同一の展開済みdbt project objectを、並列で実行できる
  4. 失敗時の復旧: エラー結果から、最新の失敗実行のアーティファクトを再利用して効率的に復旧する

本記事で扱うのは3番目の並行実行です。

例えば、次のようなプロジェクトを考えます。

models/
├── core/
│   └── core_model.sql
└── marketing/
    └── marketing_model.sql

この場合、dbt project objectを複製せず、--selectで実行対象を分けられます。

Coreスライス:
  --select path:models/core

Marketingスライス:
  --select path:models/marketing

例えば、次のようなスケジュールを構成できます。

Core       : 1時間ごと
Marketing  : 15分ごと

従来は、実行対象や実行頻度を分けるために、dbt project object自体を複製する構成になりがちでした。今回の機能では、次のようにデプロイ単位と実行単位を分離できます。

デプロイ単位:
  1つのdbt project object

実行単位:
  --selectで指定するモデルスライス

スケジュール単位:
  スライスごとに個別設定

ただし、並列実行時には、モデルが作成するテーブルだけでなく、dbtアーティファクトやログの書き込み先も考慮する必要があります。

Live versionとは

dbt project objectには、現在のプロジェクトファイルを保持する、単一の可変バージョンであるlive versionがあります。

プロジェクトを作成するとlive versionが作成され、その後のデプロイでは同じlive versionの内容が置き換えられます。Snowflake上のパスは、次の形式です。

snow://dbt/<database>.<schema>.<project>/versions/live

今回のプロジェクトでは、次のパスになります。

snow://dbt/ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO/versions/live

デプロイは、live version全体を単一操作で置き換えます。そのため、デプロイ途中の不完全なプロジェクトを実行が参照することはありません。

また、live versionには、プロジェクトのソースファイルだけでなく、writebackによって生成されたtargetlogsも保存されます。ただし、後続のデプロイではlive version全体が置き換えられるため、既存のtarget・log artifactsもデプロイ内容に含まれる形で更新されます。

今回の並列実行機能では、single mutable live versionを利用するdbt project objectが前提です。2026_06 behavior change bundleを有効化するか、Snowflakeアカウントでsingle live version機能が利用可能である必要があります。

公式ドキュメントはこちらです。

https://docs.snowflake.com/en/user-guide/data-engineering/dbt-projects-on-snowflake-live-version

Writebackとは

Writebackは、dbtの実行で生成されたtarget artifactsやログを、dbt project objectのlive versionへ書き戻す仕組みです。

dbt実行
  ├── target/
  │   ├── manifest.json
  │   └── run_results.json
  └── logs/
      └── dbt.log

          └── live versionへ書き戻し

DEFAULT_WRITEBACKは、後続の実行でwritebackするかどうかのデフォルト値です。個別の実行では、WRITEBACKを指定して、このデフォルト値を上書きできます。

WRITEBACK = FALSE

EXECUTE DBT PROJECT ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO
  ARGS = 'build --target prod --select path:models/core'
  WRITEBACK = FALSE;

WRITEBACK = FALSEの場合、実行時に生成されたtarget・log artifactsはlive versionへ書き戻されません。

一方で、Snowflakeはwritebackの設定にかかわらず、実行ごとの結果artifactsをresultsディレクトリにquery単位で保存します。そのため、並列実行時にlive versionの共有target・log pathを使う必要がなければ、WRITEBACK = FALSEが推奨されます。

WRITEBACK = TRUE

writebackを有効にしたまま並列実行する場合は、実行ごとに--target-path--log-pathを分けます。

Core:
  target/core
  logs/core

Marketing:
  target/marketing
  logs/marketing

target・log pathはプロジェクト内部のディレクトリである必要があり、並列実行間で重複してはいけません。親ディレクトリと子ディレクトリの組み合わせも避けます。

避けるべき例:

Execution A: target/
Execution B: target/marketing/

今回の検証では、以下の2パターンを確認します。

パターン1:
  WRITEBACK = FALSE

パターン2:
  WRITEBACK = TRUE
  かつ、実行ごとにtarget/log pathを分離

制限事項

  • 2026年9月11日時点では、2026_06 behavior change bundleを有効化する必要があります
  • --target-path--log-pathは、プロジェクト内のディレクトリを指す必要があり、並列実行間で重複してはいけません(親子関係になる組み合わせも避ける必要があります)
  • DEFAULT_WRITEBACK = TRUEのまま--target-path--log-pathを分けずに並列実行すると、共有パスへの書き込みが競合するリスクがあります
  • WRITEBACKは、あくまでアーティファクト・ログの書き込み先の衝突を防ぐ設定です。同じテーブルへの同時書き込みや、同じincremental model/snapshotの同時実行といったデータ側の競合までは解決しません

参考:dbt Projects on Snowflakeの基本操作について

基本的にWorkspace上で検証を進めるため、dbt projectの基本操作については以下のブログも参考にご覧ください。

https://dev.classmethod.jp/articles/dbt-quickstart-for-dbt-and-snowflake-with-dbt-projects-on-snowflake/

https://dev.classmethod.jp/articles/dbt-projects-on-snowflake-initial-setup-prod-execution-summary/

事前準備

1. Snowflakeオブジェクトの準備

検証用に、以下のオブジェクトを使用します。既存のものがあれば適宜読み替えてください。

項目
ウェアハウス DBT_CONCURRENT_DEMO_WH
データベース ANALYTICS
dbt project object配置スキーマ ANALYTICS.DBT_PROJECTS
dbt実行先スキーマ ANALYTICS.DBT
dbt project object ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO

ACCOUNTADMINで、ウェアハウス・データベース・スキーマを作成します。

USE ROLE ACCOUNTADMIN;

CREATE OR REPLACE WAREHOUSE DBT_CONCURRENT_DEMO_WH
  WAREHOUSE_SIZE = XSMALL
  AUTO_SUSPEND = 60
  AUTO_RESUME = TRUE;

CREATE DATABASE IF NOT EXISTS ANALYTICS;

CREATE SCHEMA IF NOT EXISTS ANALYTICS.DBT_PROJECTS;

CREATE SCHEMA IF NOT EXISTS ANALYTICS.DBT;

CREATE ROLE DBT_CONCURRENT_DEV_ROLE;

検証ロールに対して、必要な権限を付与します。

GRANT USAGE ON WAREHOUSE DBT_CONCURRENT_DEMO_WH
  TO ROLE DBT_CONCURRENT_DEV_ROLE;

GRANT USAGE, CREATE SCHEMA ON DATABASE ANALYTICS
  TO ROLE DBT_CONCURRENT_DEV_ROLE;

GRANT USAGE, CREATE DBT PROJECT ON SCHEMA ANALYTICS.DBT_PROJECTS
  TO ROLE DBT_CONCURRENT_DEV_ROLE;

GRANT USAGE, CREATE TABLE ON SCHEMA ANALYTICS.DBT
  TO ROLE DBT_CONCURRENT_DEV_ROLE;

GRANT ROLE DBT_CONCURRENT_DEV_ROLE TO ROLE SYSADMIN; 

2. Snowsightで検証用dbt projectを作成する

SnowsightでProjectsWorkspacesAdd newdbt Projectを選択し、プロジェクトを作成します。

項目
Project Name concurrent_demo
Role DBT_CONCURRENT_DEV_ROLE
Warehouse DBT_CONCURRENT_DEMO_WH
Database ANALYTICS
Schema DBT

2026-09-11_21h20_17

最終的に以下の構成にします。(models内のサンプルの.sqlファイルだけ削除するようにしてください。)

concurrent_demo/
├── dbt_project.yml
├── macros/
│    └── get_custom_schema.sql
└── models/
    ├── core/
    │   └── core_model.sql
    └── marketing/
        └── marketing_model.sql

`dbt_project.yml`は以下の内容にします。

```yaml
name: concurrent_demo
version: 1.0.0
config-version: 2
profile: concurrent_demo
model-paths:
  - models
analysis-paths:
  - analyses
test-paths:
  - tests
seed-paths:
  - seeds
macro-paths:
  - macros
snapshot-paths:
  - snapshots
models:
  concurrent_demo:
    core:
      +schema: DBT
      +materialized: table
    marketing:
      +schema: DBT
      +materialized: table

profiles.ymlは以下の内容にします。target: prodがポイントです。

concurrent_demo:
  target: prod
  outputs:
    prod:
      type: snowflake
      role: DBT_CONCURRENT_DEV_ROLE
      warehouse: DBT_CONCURRENT_DEMO_WH
      database: ANALYTICS
      schema: DBT
      threads: 8

macros/get_custom_schema.sqlは、以下の通り作成します。(参考ブログ

{% macro generate_schema_name(custom_schema_name, node) %}

    {% set default_schema = target.schema %}

    {# targetが「prod」かつ対象のオブジェクトが「seed」かつcustom_schemaの定義ありの場合、seed向けの「custom_schema」に #}
    {% if target.name == 'prod' and node.resource_type == 'seed' and custom_schema_name is not none %}
        {{ custom_schema_name | trim }}

    {# targetが「prod」でないかつ対象のオブジェクトが「seed」かつcustom_schemaの定義ありの場合、「default_schema」を先頭に付けたseed向けの「custom_schema」に #}
    {% elif target.name != 'prod' and node.resource_type == 'seed' and custom_schema_name is not none %}
        {{ default_schema }}_{{ custom_schema_name | trim }}

    {# targetが「prod」かつcustom_schemaの定義ありの場合、「custom_schema」に #}
    {% elif target.name == 'prod' and custom_schema_name is not none %}
        {{ custom_schema_name | trim }}

    {# custom_schemaの定義なしの場合、「default_schema」に #}
    {% elif custom_schema_name is none %}
        {{ default_schema }}

    {# 上述の条件に合致しない(targetが「prod」でないがcustom_schemaの定義あり、など)の場合、「default_schema」に #}
    {% else %}
        {{ default_schema }}
    {% endif %}

{% endmacro %}

models/core/core_model.sqlmodels/marketing/marketing_model.sqlは、それぞれ動作確認用に以下の内容にします。

-- models/core/core_model.sql
select
    1 as model_id,
    'core' as slice_name,
    current_timestamp() as executed_at
-- models/marketing/marketing_model.sql
select
    1 as model_id,
    'marketing' as slice_name,
    current_timestamp() as executed_at

coremarketingは別々のテーブル(ANALYTICS.DBT.CORE_MODELANALYTICS.DBT.MARKETING_MODEL)として作成されるため、並列実行してもデータ側の書き込み先が重複しない構成です。

この状態で、一度targetprodに対してdbt runを実行して、問題なく実行できてテーブルが作成されれば、準備完了です。

2026-09-11_21h40_20

試してみた

1. Workspaceからdbt projectをデプロイする

WorkspaceのConnectを選択し、Deploy dbt projectをクリックします。

デプロイ画面では、以下を指定します。(今回は検証のためtargetをprodだけ設定していますが、本番運用時はdevなどの開発用targetを作成するようにしてください。)

項目
Select location ANALYTICS.DBT_PROJECTS
Select or Create dbt project Create dbt project
Enter name CONCURRENT_DEMO
Default target prod
Default Writeback 無効化

2026-09-11_21h42_55

デプロイが成功すれば下図のように表示されます。

2026-09-11_21h43_56

デプロイ結果は、SQLで確認します。

DESCRIBE DBT PROJECT ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO;

default_versionLIVEになっていれば、single mutable live versionとしてデプロイされています。

2026-09-11_21h45_02

2. WRITEBACK = FALSEで並列実行する

ここから本題の並列実行です。まずはwritebackを無効化したパターンから試します。

Worksheet Aで、Coreスライスを実行します。

EXECUTE DBT PROJECT ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO
  ARGS = 'build --target prod --select path:models/core'
  WRITEBACK = FALSE;

別のセッション(Worksheet B)から、できるだけ同じタイミングでMarketingスライスを実行します。

EXECUTE DBT PROJECT ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO
  ARGS = 'build --target prod --select path:models/marketing'
  WRITEBACK = FALSE;

SnowsightのTransformationsdbt ProjectsCONCURRENT_DEMORun Historyを開くと、2つのdbtコマンドが同時に実行されていることが確認できました。

2026-09-11_21h51_07

3. WRITEBACK = TRUEで並列実行する(target-path・log-pathを分離)

続いて、writebackを有効にしたまま、実行ごとに--target-path--log-pathを分けて並列実行します。

Worksheet Aで、Coreスライスを実行します。

EXECUTE DBT PROJECT ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO
  ARGS = 'build --target prod --select path:models/core --target-path target/core --log-path logs/core --log-level-file info'
  WRITEBACK = TRUE;

Worksheet Bで、できるだけ同じタイミングでMarketingスライスを実行します。

EXECUTE DBT PROJECT ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO
  ARGS = 'build --target prod --select path:models/marketing --target-path target/marketing --log-path logs/marketing --log-level-file info'
  WRITEBACK = TRUE;

--target-path--log-pathは、以下のように実行ごとに完全に分離しています。親子関係になる組み合わせ(例: target/target/marketing/を同時に使う)は避けてください。

Core:
  target/core
  logs/core

Marketing:
  target/marketing
  logs/marketing

Run Historyは以下のように表示されればOKです。

2026-09-11_21h58_38

4. live versionに書き戻されたtarget・logsを確認する

WRITEBACK = TRUEで書き戻されたアーティファクトが、実際に分離したパスへ格納されているかを、COPY FILESで確認します。

まず、確認用の内部ステージを作成します。

CREATE OR REPLACE STAGE ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO_CHECK_STAGE
  ENCRYPTION = (TYPE = 'SNOWFLAKE_SSE');

live versionのtargetlogsを、スライスごとにステージへコピーします。

COPY FILES INTO @ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO_CHECK_STAGE/core/
  FROM 'snow://dbt/ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO/versions/live/target/core/';

COPY FILES INTO @ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO_CHECK_STAGE/core/
  FROM 'snow://dbt/ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO/versions/live/logs/core/';

COPY FILES INTO @ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO_CHECK_STAGE/marketing/
  FROM 'snow://dbt/ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO/versions/live/target/marketing/';

COPY FILES INTO @ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO_CHECK_STAGE/marketing/
  FROM 'snow://dbt/ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO/versions/live/logs/marketing/';

ステージ内のファイルを一覧表示します。

LIST @ANALYTICS.DBT_PROJECTS.CONCURRENT_DEMO_CHECK_STAGE;

下図のように、指定したパスに分けて各種アーティファクトのファイルが出力されていればOKです。--target-path--log-pathを分けたことで、writeback有効時でも並列実行のアーティファクトが衝突せず、live version配下にスライスごとに書き戻されていることが確認できました。

2026-09-11_22h01_21

なお参考までに、writebackとは別に、実行ごとのアーティファクトはquery単位でも保存されており、Run Historyから対象の実行を開き、Query Detailsタブのdbt OutputにあるDownload Build ArtifactsからもZIPでダウンロードできます。

2026-09-11_22h02_42

最後に

dbt Projects on SnowflakeのSlim CI/defer to production GAに含まれる「並行実行」機能を使い、同一のdbt project objectに対してcoremarketingという独立したモデルのbuildを並列実行できるか試してみました。

WRITEBACK = FALSEにするか、WRITEBACK = TRUEのまま--target-path--log-pathを実行ごとに分離するかのどちらかを選べば、共有のliveパスへの書き込み衝突を避けつつ並列実行できることが確認できました。

これまで、並列で実行したいモデル群がある場合はdbt project object自体を複製していた構成では、モデルの追加・変更のたびに複数のデプロイ先を意識する必要がありましたが、今回の機能でデプロイ単位と実行単位を分離し、1つのdbt project objectを複製せずに並列実行できるようになったのは、運用上大きな強みだと感じました。

ぜひ、ご活用ください!


Snowflake World Tour Tokyo 2026に参加しませんか?

Snowflakeの国内最大級イベント「Snowflake World Tour Tokyo」が2026年9月10日(木)・11日(金)にグランドプリンスホテル新高輪にて開催されます。
最新のAI・データ活用事例やライブデモを体感できる無料イベントです。

Snowflake World Tour Tokyoイベントに参加する


Snowflake Community Awards ファイナリストに選出されました

DevelopersIO で Snowflake 記事を執筆している かわばた が、Snowflake Community Awards「RISING COMMUNITY LEADER OF THE YEAR」部門・APJ枠のファイナリストに選ばれました。
最終選考の30%はコミュニティ投票です。記事がお役に立っていたようでしたら、9月15日(火)までにぜひ一票お願いします。フォームの「(4 of 6) RISING COMMUNITY LEADER OF THE YEAR」で Tomohiro Kawabata | Classmethod, Japan を選択、2分ほどで完了します。

投票フォームを開く


Snowflakeの導入支援はクラスメソッドに!

クラスメソッドでは Snowflake の導入を支援しております。
製品の詳細や支援の内容についてお気軽にお問い合わせください。

Snowflakeの詳細を見る

この記事をシェアする

関連記事