🐼

ソースコードから読み解く dbt runの裏側(Snowflake) — 実行SQLと必要権限の整理

に公開

この記事は、Nowcast Advent Calendar 2025 の12日目の記事です。

https://qiita.com/advent-calendar/2025/nowcast

はじめに

はじめまして。ナウキャストの高橋です。

今回は、dbt-coreのソースコードを見ながら、dbt runが実行する各SQLと必要な権限について整理してみました。materializationごとの実行フローを踏まえて、実践的な権限設計についても解説します。

この記事を読むことで、dbt runで実行される処理フロー・SQLとそのためのSnowflakeの権限設定の方法を把握することができます。

調査対象

背景

Snowflakeのデータ変換の管理をdbtで管理することが多いのですが、「dbtが裏側でどんな処理をしているのか」、「どんなSQLを実行しているのか」について、ちゃんと整理したことがなかったので、今回改めて整理してみようと思いました。

今回は、dbtのメイン処理のdbt runコマンドの裏側で実行されてるフローについて整理していきます。

  1. dbt runで実行される処理フローと実行SQL
  2. dbt実行に必要な権限まとめ
  3. Database Roleを活用した権限設計
  4. まとめ

dbt runで実行される処理フローと実行SQL

実行フローの全体像

dbt runは以下の3フェーズで構成されます。本記事では、Snowflakeで実際に発行されるSQLに焦点を当て、SQL実行を伴わない内部処理は割愛します。

1. 初期化処理(Phase 1)

はじめに、モデル実行前の実行計画を決めるために必要な情報を取得するSQLの実行とon-run-start hooksの実行を行います。この初期化処理フェーズはどのmaterializedでも共通の処理になります。

ステップ 実行SQL 実行条件 必要権限
① スキーマ一覧取得 SHOW SCHEMAS IN DATABASE <db>; リレーショナルモデル実行時 USAGE on DATABASE
② スキーマ作成 CREATE SCHEMA IF NOT EXISTS <db>.<schema>; スキーマ未存在時 CREATE SCHEMA on DATABASE
③ オブジェクトキャッシュ SHOW TERSE OBJECTS IN SCHEMA <db>.<schema>; デフォルト(--no-populate-cacheで無効化) USAGE on SCHEMA
④ on-run-start hooks 任意のSQL on-run-start定義時 フック内容に依存

2. モデル実行(Phase 2)

各materializedの実行フローの概要は以下の通りです。

materialized 初回実行 2回目以降 処理内容 追加権限(初回実行) 追加権限(2回目以降)
table CREATE OR REPLACE TABLE CREATE OR REPLACE TABLE テーブルの作成・更新 CREATE TABLE on SCHEMA CREATE TABLE on SCHEMA, OWNERSHIP on TABLE(既存テーブル上書き時)
view CREATE OR REPLACE VIEW CREATE OR REPLACE VIEW ビュー定義の作成・更新 CREATE VIEW on SCHEMA CREATE VIEW on SCHEMA, OWNERSHIP on VIEW
incremental CREATE TABLE INSERT/MERGE/DELETE
CREATE TABLE/VIEW
増分処理 CREATE TABLE on SCHEMA CREATE TABLE/VIEW on SCHEMA(ステージ/一時作成)
INSERT, UPDATE, DELETE(または MERGE 実行に必要な権限) on TABLE

※ 作成するモデルが参照するTABLE/VIEWに対するSELECT権限も必要になります。権限付与漏れに注意してください。

2-a. モデル実行時の共通処理

各materializationの実行では、上記の主要処理に加えて、以下のような共通処理が実行されます。materializationごとのモデル更新は、2.pre-hookと3.post-hookの間で実行されます。

  1. クエリタグの設定・解除: ALTER SESSION SET/UNSET QUERY_TAGによる実行クエリへのタグ付与
  2. pre-hook: モデル実行前に任意のSQLを実行するフック処理
  3. post-hook: モデル実行後に任意のSQLを実行するフック処理
  4. 権限の適用: apply_grantsによる明示的な権限付与
  5. ドキュメント永続化: persist_docsによるCOMMENT ON文の実行
  6. 既存リレーションの確認: SHOW TABLES/VIEWS LIKE ...によるキャッシュミス時の確認処理

次に、materializationごとのモデル更新の詳細について、個別に解説していきます。


2-b. materialized = table

materialized = table におけるモデル更新部分は以下の部分になります。

https://github.com/dbt-labs/dbt-adapters/blob/0063f5215c33e6c5d6ca9e3a7b3ed52b5ae18911/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/table.sql#L23-L29

{% if target_relation.needs_to_drop(existing_relation) %}の部分では、icebergテーブルと非icebergテーブル間で別の形式への変換があるかを判定し、変換がある場合は既存リレーションの事前dropが実行されています。

create_table_as(temporary, relation, compiled_code, language='sql')では、テーブル作成を行います。create_table_asmacroを見てみると、下記のにあるように、create or replace table as文を実行しシンプルにテーブルの作成・置換を実行しています。

実行順 実行SQL / 処理内容 実行タイミング 必要権限 備考
0 ALTER SESSION SET QUERY_TAG クエリタグ設定 (set_query_tag) - 実行クエリにタグを付与
1 SHOW TABLES LIKE '<table>' IN SCHEMA <db>.<schema>; キャッシュミス時 (既存テーブル確認) USAGE on SCHEMA 既存の関係性を取得
2 pre-hook(任意のSQL) pre_hook設定時 フック内容に依存 run_hooks(pre_hooks)
3 CREATE [OR REPLACE] TABLE <target_relation> AS ... 常に実行 CREATE TABLE on SCHEMA
SELECT on ソースTABLE/VIEW
create_table_asマクロ内で展開
4 post-hook(任意のSQL) post_hook設定時 フック内容に依存 run_hooks(post_hooks)
5 権限の適用(apply_grants grants設定時 OWNERSHIP on TABLE apply_grants
6 COMMENT ON TABLE/COLUMN ... persist_docs設定時 OWNERSHIP on TABLE persist_docs
7 ALTER SESSION UNSET QUERY_TAG 常に実行 (unset_query_tag) - クエリタグを元の設定に戻す

該当のmaterializationコード全文はこちらになります。

https://github.com/dbt-labs/dbt-adapters/blob/main/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/table.sql

余談ですが、dbt-redshiftなど他のadapter(v1.10.4)では、以下のように一時テーブルを作成しスワップする形でテーブル更新を実行しているものもあるので、他のadapterとごっちゃにならないように注意です。

https://github.com/dbt-labs/dbt-adapters/blob/0063f5215c33e6c5d6ca9e3a7b3ed52b5ae18911/dbt-redshift/src/dbt/include/redshift/macros/materializations/table.sql#L26-L51

  1. 一時テーブルの作成(データ投入)
  2. 旧テーブルのリネーム(バックアップ):
  3. スワップ(一時テーブルを旧テーブルと同じ名前にリネーム)
  4. 旧テーブルのドロップ

2-c. materialized = view

materialized = view におけるモデル更新部分は以下の部分になります。

https://github.com/dbt-labs/dbt-adapters/blob/0063f5215c33e6c5d6ca9e3a7b3ed52b5ae18911/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/view.sql#L4

create_or_replace_viewはglobal_projects内にありました。作成するVIEWと同名同名のテーブルが既存に存在しなければ、snowflake__create_or_replace_viewが実行されVIEWが作成されます。

実行順 実行SQL / 処理内容 実行タイミング 必要権限 備考
0 ALTER SESSION SET QUERY_TAG = ...set_query_tag 常に実行 - 実行クエリにタグを付与
2 pre-hook(任意のSQL) pre_hook設定時 フック内容に依存 run_hooks(pre_hooks)
3 CREATE OR REPLACE [SECURE] VIEW <target_relation> AS (<compiled_code>); 常に実行 CREATE VIEW on SCHEMA
ビューが存在する場合: OWNERSHIP on 既存VIEW
SELECT on ソースTABLE/VIEW
create_or_replace_viewが実行されるため、既存オブジェクトを先にDROPする必要はない
4 post-hook(任意のSQL) post_hook設定時 フック内容に依存 run_hooks(post_hooks)
5 権限の適用(apply_grants grants設定時 OWNERSHIP on VIEW apply_grants
6 COMMENT ON VIEW/COLUMN ... persist_docs設定時 OWNERSHIP on VIEW persist_docs
7 ALTER SESSION UNSET QUERY_TAG(unset_query_tag) 常に実行 - クエリタグを元の設定に戻す

該当のmaterializationコード全文はこちらになります。

https://github.com/dbt-labs/dbt-adapters/blob/main/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/view.sql


2-d. materialized = incremental

materialized = incrementalでは、初回は全データをロードし、2回目以降は一時リレーション(TEMPORARY VIEW/TABLE)を使って増分処理を実行します。実行内容はincremental_strategyによって異なります。

初回実行・full_refresh時

初回実行・full_refreshでは既存のテーブルが存在しないので、materialized=tableと同じ処理create_table_as(False, target_relation, compiled_code, language)が実行されています。

https://github.com/dbt-labs/dbt-adapters/blob/0063f5215c33e6c5d6ca9e3a7b3ed52b5ae18911/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql#L119-L125

実行順 実行SQL 実行タイミング 必要権限
0 ALTER SESSION SET QUERY_TAG = ... クエリタグ設定 -
1 pre-hook(任意のSQL) pre_hook設定時 フック内容に依存
2 CREATE TABLE <db>.<schema>.<table> AS (SELECT ...); 初回 or full_refresh CREATE TABLE on SCHEMA
SELECT on ソースTABLE/VIEW
3 post-hook(任意のSQL) post_hook設定時 フック内容に依存
4 権限の適用(apply_grants grants設定時 OWNERSHIP on TABLE
5 COMMENT ON TABLE/COLUMN ... persist_docs設定時 OWNERSHIP on TABLE
6 ALTER SESSION UNSET QUERY_TAG 常に実行 (unset_query_tag) -
増分実行時

増分更新時の共通フロー

増分更新時には、一時リレーションを作成・利用し、strategyに応じたDMLを実行します。以下に、どのstrategyでも共通で実行される全体フローを整理します。(strategyに応じたDMLについては後述します。)

他のmaterializedと比べて、安全に増分更新処理を行うための、一時リレーション作成やスキーマ変更処理が追加で実行されていますね。

実行順 処理内容 実行タイミング 必要権限 備考
0 ALTER SESSION SET QUERY_TAG = ... 常に実行 - set_query_tag
1 pre-hook実行 pre_hook設定時 フック内容に依存
2 一時リレーション作成 常に実行 CREATE VIEWまたはCREATE TABLE on SCHEMA strategyによりVIEW/TABLEが異なる
3 スキーマ変更処理 on_schema_change設定時 OWNERSHIP on TABLE ターゲットテーブルのスキーマを更新
4 strategy別SQL実行 常に実行 strategyにより異なる INSERT, MERGE, DELETE/INSERT など
5 権限の適用(apply_grants grants設定時 OWNERSHIP on TABLE
6 COMMENT ON TABLE/COLUMN ... persist_docs設定時 OWNERSHIP on TABLE
7 post-hook実行 post_hook設定時 フック内容に依存
8 一時リレーション削除 常に実行 OWNERSHIP on 一時リレーション post-hook後に実行される
9 ALTER SESSION UNSET QUERY_TAG 常に実行 - unset_query_tag

strategy別の詳細

以下に、前述したstrategy別SQL実行部分について、実行されるSQLをまとめます。

strategy 一時リレーション SQL/処理内容 必要権限 備考
append VIEW INSERT INTO <table> SELECT * FROM <tmp_view>; INSERT on TABLE 単純追記。重複チェックなし。
merge (デフォルト) VIEW MERGE INTO <table> USING <tmp_view> ON <unique_key> ... INSERT, UPDATE, DELETE on TABLE unique_keyに基づき更新・挿入。
delete+insert (unique_keyあり) TABLE 1. CREATE TEMPORARY TABLE ...
2. DELETE FROM <table> WHERE ...
3. INSERT INTO <table> ...
CREATE TABLE on SCHEMA
DELETE, INSERT on TABLE
unique_keyで既存データを削除してから挿入。
delete+insert (unique_keyなし) VIEW INSERT INTO <table> SELECT * FROM <tmp_view>; INSERT on TABLE appendと同じ。DELETE処理なし。

さらに、以下にソースコードの該当箇所と照らし合わせながら、実行フローをもう少し深ぼっていきますね(実行フローだけを知りたい方は、ソースコード部分は読み飛ばしてください...。)

1. dbt_snowflake_get_tmp_relation_type()で増分実行時に使用する一時リレーション(モデルのコンパイル済みSQL結果を保持する中間オブジェクト)が、table (一時テーブル) になるか、view (一時ビュー) になるかを決定します。

https://github.com/dbt-labs/dbt-adapters/blob/0063f5215c33e6c5d6ca9e3a7b3ed52b5ae18911/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql#L92

2. (表では省略してますが...)既存に同名のVIEWが存在する場合は、以下の部分で強制的にviewをドロップしています。既存のVIEWと同名の増分モデルを作成する際は注意しましょう。

https://github.com/dbt-labs/dbt-adapters/blob/0063f5215c33e6c5d6ca9e3a7b3ed52b5ae18911/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql#L111-L117

3. 1で判定した結果に基づき、一時リレーションを作成します。

https://github.com/dbt-labs/dbt-adapters/blob/0063f5215c33e6c5d6ca9e3a7b3ed52b5ae18911/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql#L94-L98

4. 作成した一時リレーションに基づいて、ターゲットテーブルのカラム型の更新が必要だった場合、カラムの更新を実行します

https://github.com/dbt-labs/dbt-adapters/blob/0063f5215c33e6c5d6ca9e3a7b3ed52b5ae18911/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql#L152-L156

5. incremental_strategyに対応して、更新SQLを実行します。

https://github.com/dbt-labs/dbt-adapters/blob/0063f5215c33e6c5d6ca9e3a7b3ed52b5ae18911/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql#L158-L165

6. 一時リレーションの削除

https://github.com/dbt-labs/dbt-adapters/blob/0063f5215c33e6c5d6ca9e3a7b3ed52b5ae18911/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql#L169

該当のmacroコード全文はこちらになります。

https://github.com/dbt-labs/dbt-adapters/blob/main/dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql

dbt実行に必要な権限まとめ

ここまで、dbt runで実行される処理の処理の流れについて見てきました。次に、これらの処理を実行するためのSnowflakeに対する権限について見ていきましょう。

以下、dbt runで使用する機能と必要なSnowflake権限の対応表です(✅: 必須、🔵: 条件付き)。

基本処理の権限

処理 USAGE
DATABASE
USAGE
SCHEMA
CREATE
SCHEMA
スキーマ一覧取得
スキーマ作成 🔵
オブジェクトキャッシュ

materialized別の権限

materialized 実行タイミング USAGE
DATABASE
USAGE
SCHEMA
CREATE
SCHEMA
CREATE
TABLE
CREATE
VIEW
OWNERSHIP
TABLE/VIEW
INSERT UPDATE DELETE SELECT
ソース
table 初回実行 🔵
2回目以降 🔵
view 初回実行 🔵
2回目以降 🔵
incremental 初回実行 🔵
append 🔵
merge(デフォルト) 🔵
delete+insert
(unique_key有)
🔵
delete+insert
(unique_key無)
🔵

オプション機能の権限

機能 OWNERSHIP
TABLE/VIEW
on_schema_change
persist_docs

最小権限まとめ

これまでの整理から、dbt runに必要な最小権限は以下のようになりました。

基本権限(必須)

  • DATABASE: USAGE
  • SCHEMA: USAGE, CREATE TABLE, CREATE VIEW
  • TABLE/VIEW(ソース): SELECT
  • WAREHOUSE: USAGE

materialization別の追加権限

  • table: OWNERSHIP on TABLE(RENAME処理と旧テーブルのDROP処理に必要)
  • view: 既存オブジェクト種別が異なる場合、その既存オブジェクト(TABLE/VIEW)のOWNERSHIPが必要
  • incremental:
    • 初回/full_refresh: 追加権限不要
    • append: INSERT, OWNERSHIP(一時view削除)
    • merge: INSERT, UPDATE, DELETE, OWNERSHIP(一時view削除)
    • delete+insert(unique_key有): INSERT, DELETE, OWNERSHIP(一時table削除)
    • delete+insert(unique_key無): INSERT, OWNERSHIP(一時view削除)

Database Roleを活用した権限設計

SnowflakeのDatabase Role機能を活用することで、スキーマ単位で権限を管理し、保守性の高い設計が実現できます。

設計原則

  1. スキーマごとにDatabase Roleを作成し、権限をカプセル化
  2. ALL/FUTURE権限でオブジェクトの自動権限付与を実現
  3. Roleの階層化により、上位Roleが下位Roleの権限を継承
  4. Account RoleとDatabase Roleを分離し、管理を簡素化

権限構造

実装例

以下は1スキーマあたりの設定パターンです。このテンプレートを各スキーマに適用することで、統一的な権限管理が実現できます。

-----------------------------------------------------------------------------
-- 1. Database Roleの作成
-----------------------------------------------------------------------------

-- SELECT権限用のDatabase Role(テーブル)
CREATE DATABASE ROLE IF NOT EXISTS "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_TABLE"
    COMMENT = 'Access role with SELECT permissions on <SCHEMA> TABLES';

-- SELECT権限用のDatabase Role(ビュー)
CREATE DATABASE ROLE IF NOT EXISTS "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_VIEW"
    COMMENT = 'Access role with SELECT permissions on <SCHEMA> VIEWS';

-- OWNERSHIP権限用のDatabase Role(テーブル)
CREATE DATABASE ROLE IF NOT EXISTS "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_TABLE"
    COMMENT = 'Access role with OWNERSHIP permissions on <SCHEMA> TABLE';

-- OWNERSHIP権限用のDatabase Role(ビュー)
CREATE DATABASE ROLE IF NOT EXISTS "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_VIEW"
    COMMENT = 'Access role with OWNERSHIP permissions on <SCHEMA> VIEW';

-- スキーマ全体のOWNERSHIP権限用のDatabase Role
CREATE DATABASE ROLE IF NOT EXISTS "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_SCHEMA"
    COMMENT = 'Access role with OWNERSHIP permissions on <SCHEMA>';

-----------------------------------------------------------------------------
-- 2. SELECT権限の付与(テーブル)
-----------------------------------------------------------------------------

-- 基本権限
GRANT USAGE ON DATABASE "<DATABASE>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_TABLE";
GRANT USAGE ON SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_TABLE";

-- ALL/FUTURE権限(既存と将来のオブジェクトに対して)
GRANT SELECT, REFERENCES ON ALL TABLES IN SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_TABLE";
GRANT SELECT, REFERENCES ON FUTURE TABLES IN SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_TABLE";

-----------------------------------------------------------------------------
-- 3. SELECT権限の付与(ビュー)
-----------------------------------------------------------------------------

GRANT USAGE ON DATABASE "<DATABASE>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_VIEW";
GRANT USAGE ON SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_VIEW";

GRANT SELECT, REFERENCES ON ALL VIEWS IN SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_VIEW";
GRANT SELECT, REFERENCES ON FUTURE VIEWS IN SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_VIEW";

-----------------------------------------------------------------------------
-- 4. Database Roleの階層化
-----------------------------------------------------------------------------

-- OWNERSHIP権限にSELECT権限を含める
GRANT DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_TABLE" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_TABLE";
GRANT DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_SELECT_VIEW" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_VIEW";

-- スキーマ全体のOWNERSHIPにテーブル・ビューのOWNERSHIPを含める
GRANT DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_TABLE" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_SCHEMA";
GRANT DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_VIEW" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_SCHEMA";

-----------------------------------------------------------------------------
-- 5. OWNERSHIP権限の付与
-----------------------------------------------------------------------------

-- スキーマのOWNERSHIPを付与
GRANT OWNERSHIP ON SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_SCHEMA" 
    COPY CURRENT GRANTS;

-- テーブルのOWNERSHIP権限(ALL/FUTURE)
GRANT OWNERSHIP ON ALL TABLES IN SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_TABLE" 
    COPY CURRENT GRANTS;
GRANT OWNERSHIP ON FUTURE TABLES IN SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_TABLE" 
    COPY CURRENT GRANTS;

-- ビューのOWNERSHIP権限(ALL/FUTURE)
GRANT OWNERSHIP ON ALL VIEWS IN SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_VIEW" 
    COPY CURRENT GRANTS;
GRANT OWNERSHIP ON FUTURE VIEWS IN SCHEMA "<DATABASE>"."<SCHEMA>" 
    TO DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_VIEW" 
    COPY CURRENT GRANTS;

-----------------------------------------------------------------------------
-- 6. Account RoleへのDatabase Role付与
-----------------------------------------------------------------------------

-- dbt実行用のAccount RoleにOWNERSHIP_SCHEMAを付与
GRANT DATABASE ROLE "<DATABASE>"."ACCESS_<SCHEMA>_OWNERSHIP_SCHEMA" 
    TO ROLE <DBT_ROLE>;

-----------------------------------------------------------------------------
-- 7. WarehouseのUSAGE権限付与
-----------------------------------------------------------------------------
GRANT USAGE ON WAREHOUSE <WAREHOUSE_NAME>
    TO ROLE <DBT_ROLE>;

運用上のポイント

Role階層化

上位RoleにSELECT Roleを含めることで、dbt実行Roleが自動的にソースデータアクセス権を取得できるようにします。

ALL/FUTURE権限

dbtではモデル開発者が、モデルを流動的に作成・更新をするため、スキーマ内のTABLE/VIEWに対するFUTURE権限も併せて付与することで、管理が容易になります。

データベースロールにOWNERSHIPを付与

データベースロールにOWNERSHIPを付与することで、サービスユーザーやヒューマンユーザーが異なるアカウントロールを使用して実行をしても、オブジェクトの所有権が勝手に変わらないようになってます。

dbtのgrants機能は原則利用しない

dbtには、モデル実行後にdbtが作成したオブジェクトに対して権限を付与する機能がありますが、以下の理由で本記事ではgrants機能は原則推奨しないです。

  • 権限の二重管理を避けるため
  • 開発者がモデル開発に集中できるように

どうしてもこの機能を使いたい場合は、dbtのconfig(copy_grants)をtrueにして、置換時に既存の権限を維持できるため、apply_grantsの再適用を減らしましょう。

まとめ

ここまで読んでいただきありがとうございます。

今回は、dbt run実行時の実行フローと必要な権限について改めて整理してみました。なんとなく、「こんなふうに動いているんだろうな」とふわっと理解してましたが、実際に実行されるクエリと向き合って、意外と新しい発見も多くとても勉強になりました。

dbtには、他にも様々なコマンドやmaterialized設定がありますので、これらもしっかり中身を理解しながら使っていきたいです。

他にも、dbtの機能について、弊社エンジニアが解説している記事もありますので、よかったらこちらも併せてご覧ください。

https://zenn.dev/finatext/articles/dbt-seed-how-it-works

https://zenn.dev/finatext/articles/dbt-snowflake-important-configurations

https://zenn.dev/finatext/articles/dbt-high-performance-incremental-model

https://zenn.dev/finatext/articles/f8d312c7fd6977

https://zenn.dev/finatext/articles/378ae349006b65

https://zenn.dev/finatext/articles/61c4a1bf4a2a1e

Finatext Tech Blog

Discussion