❄️

チュートリアル実践:dbt Project on Snowflake

に公開

2025年06月に登場以降、非常に大きな注目を浴びている『dbt Projects on Snowflake』。
https://docs.snowflake.com/en/user-guide/data-engineering/dbt-projects-on-snowflake

既に多くの方が実践・知見の共有を行っていますが私も改めてこの機能について実践してみました。当エントリでは下記チュートリアルの実践内容を紹介致します。手順は極力省略せず、画面キャプチャ多めです。

https://docs.snowflake.com/en/user-guide/tutorials/dbt-projects-on-snowflake-getting-started-tutorial

#1. はじめに

やること

dbt Project on Snowflakeのワークスペースを作成する手順に関する実践内容は以下の通り。

  • ワークスペースはフォークされたGitHubリポジトリに接続する形を取る
  • ワークスペースを使用してdbtプロジェクトのファイルを更新
  • dbtプロジェクトをテスト及び実行
  • dbtプロジェクトのデータモデル出力が対象のSnowflakeデータベースとスキーマにマテリアライズ
  • プロジェクトのデプロイを行い、Snowflake上にdbtプロジェクトオブジェクトを作成
  • 定義したスケジュールでプロジェクトを実行するタスクを設定

前提条件

実践遂行に必要なものは以下の要素、条件。

  • GitHubアカウント(Snowflake環境が接続を行うためのリポジトリを作成)
  • Gitコマンドラインの利用
  • Snowflakeアカウント
    • 下記ドキュメントで説明されている権限を持つ環境であればOK
    • 下記の要素を作成及び編集する権限、または各オブジェクトを代わりに作成出来る管理者へのアクセス
      • API統合(An API integration)
      • GitHubリポジトリをPrivateにする場合、Secret
      • ネットワークルール
      • ネットワークルールを参照する外部アクセス統合
      • ユーザーオブジェクト
      • セカンダリロール(の有効化)
      • ウェアハウス、データベース及びデータベース配下で必要となる各種Snowflakeオブジェクト

事前準備(Git環境のセットアップ)

何はともあれ、GitHub環境が必要となります。もし持っていなければ無料アカウントを作成しておきましょう。

https://github.com/

% brew install git
% git --version
git version 2.39.5 (Apple Git-154)

## その他各種コマンドでGitHubへの疎通まで済ませておく

事前準備(Snowflake環境の用意(トライアル))

GitHub同様にSnowflake環境も個別で必要となります。既存環境がある場合はそちらを使うでも勿論問題ありませんが、当エントリではSnowflakeトライアル環境を利用することにします。所定の手順に従ってSnowflakeトライアル環境を用意し、指定した認証情報でアカウントにアクセスできるようにしておいてください。


#2. 環境設定

#2-1. 「dbt Projects on Snowflake」入門用リポジトリのdbtプロジェクトをフォーク&クローン

ここではPublic及びPrivateそれぞれのリポジトリフォーク&クローンの手順を示します。実践自体は後者のPrivateな方で進めていきます。

Publicリポジトリの場合

当エントリで実践するチュートリアル用に用意された下記リポジトリにアクセスし、
https://github.com/Snowflake-Labs/getting-started-with-dbt-on-snowflake

対象内容をフォークします。(画面上部[Fork]メニューから[Create a new fork]を選択)

内容を確認しフォーク実施。

フォークしたリポジトリのURLは後ほど利用します。URLを控えておいてください。URL形式は以下のような形になっています。

https://github.com/my-github-account/getting-started-with-dbt-on-snowflake.git

Privateリポジトリの場合

上記手順でリポジトリをフォーク&クローンする流れだとPublicな形でリポジトリが作成され、後で
Privateに変更することが出来ません。

個人的な入門用のコンテンツとは言え、Publicな状態で残ってしまうのはちょっとアレなのでここはPrivateなリポジトリとして用意する流れで進めたいと思います。

参考:

GitHubにログインした状態でリポジトリの枠だけ用意します。画面左上の[New]を押下。

Privateなリポジトリを用意します。[Choose Visibility]をPrivateに切り替え、[Create Repository]を押下。

Privateリポジトリ(の枠)を作成しました。リポジトリのURLは控えておいてください。

以下の流れでそれぞれgit clonegit pushコマンドを実行。


% pwd
## チュートリアル関連のGitHubリポジトリ群をまとめておくフォルダで作成しています.
/Users/xxxxxxxxx/Xxxxxxx/shinyaa31-tutorials/

## リポジトリのClone.
% git clone --bare https://github.com/Snowflake-Labs/getting-started-with-dbt-on-snowflake.git
Cloning into bare repository 'getting-started-with-dbt-on-snowflake.git'...
remote: Enumerating objects: 101, done.
remote: Counting objects: 100% (48/48), done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 101 (delta 33), reused 22 (delta 22), pack-reused 53 (from 1)
Receiving objects: 100% (101/101), 22.87 KiB | 4.57 MiB/s, done.
Resolving deltas: 100% (35/35), done.

## リポジトリのPush.
% cd getting-started-with-dbt-on-snowflake.git
% git push --mirror git@github.com:XXXXXXXXXXXX/getting-started-with-dbt-on-snowflake.git
Enumerating objects: 101, done.
Counting objects: 100% (101/101), done.
Delta compression using up to 10 threads
Compressing objects: 100% (53/53), done.
Writing objects: 100% (101/101), 22.87 KiB | 22.87 MiB/s, done.
Total 101 (delta 35), reused 101 (delta 35), pack-reused 0
remote: Resolving deltas: 100% (35/35), done.
To github.com:XXXXXXXXXXXX/getting-started-with-dbt-on-snowflake.git
 * [new branch]      main -> main

Privateなリポジトリとして用意することが出来ました。以降はこちらのリポジトリを用います。

#2-2. ワークスペースアクションを実行するためのウェアハウスを作成

今回のチュートリアル用のウェアハウスを作成。ドキュメントでは「扱うデータが多いのでXLARGEにしといたほうがいいよ」ってあったけど一旦ここでは大事を取って最小サイズのX-SMALLにしておきます。必要に応じて変える方針で。あとAUTO_SUSPEND設定も有効化しておきます。

CREATE OR REPLACE WAREHOUSE tasty_bytes_dbt_wh
WITH
    WAREHOUSE_TYPE = STANDARD
    WAREHOUSE_SIZE='X-SMALL'
    AUTO_RESUME = TRUE
    AUTO_SUSPEND = 60
    COMMENT = 'for blog. / Tutorial: Getting started with dbt Projects on Snowflake';

#2-3. 統合とモデルの具体化のためにデータベースとスキーマを作成

作業を進めていくにあたり必要な要素としてデータベースとスキーマをそれぞれ作成します。

CREATE DATABASE tasty_bytes_dbt_db;
CREATE SCHEMA tasty_bytes_dbt_db.integrations;
CREATE SCHEMA tasty_bytes_dbt_db.dev;
CREATE SCHEMA tasty_bytes_dbt_db.prod;

#2-4. GitHubに接続するためのSnowflakeでのAPI統合を作成

SnowflakeがGitHubとやり取りするために必要な「API統合(API integration)」を作成します。

対象リポジトリがPrivateの場合は別途手順を踏む必要があるので従います。

リポジトリの個人アクセストークンを取得

下記GitHubのドキュメントに従い対応するアクセストークンを作成。

作成出来たら値をコピーしておきます。

GitHubのユーザー名をUSERNAMEに、上記で取得したアクセストークンをPASSWORDに設定しSECRETを作成。

USE tasty_bytes_dbt_db.integrations;
CREATE OR REPLACE SECRET tasty_bytes_dbt_db.integrations.tb_dbt_git_secret
  TYPE = password
  USERNAME = 'xxxxxxxxx'
  PASSWORD = 'github_xxxxxxXXXXXxXXXxxxxxxx';

そしてSECRETを使ってAPI統合を作成。API_ALLOWED_PREFIXESの箇所は対象となるGitHubアカウントのURLに置き換えてください。

CREATE OR REPLACE API INTEGRATION tb_dbt_git_api_integration
  API_PROVIDER = git_https_api
  API_ALLOWED_PREFIXES = ('https://github.com/my-github-account')
  -- Comment out the following line if your forked repository is public
  ALLOWED_AUTHENTICATION_SECRETS = (tasty_bytes_dbt_db.integrations.tb_dbt_git_secret)
  ENABLED = TRUE;

#2-5. Snowflakeでdbt依存関係の外部アクセス統合を作成

Snowflakeワークスペースでdbtコマンドを実行した際、依存関係をダウンロードするためにリモート URL にアクセスする必要がある場合があります。たとえば、dbt パッケージハブや GitHub からパッケージをダウンロードする必要がある場合があります。

この際、リモートURLから依存ファイルを取得するには、Snowflakeにネットワークルールに依存する外部アクセス統合が必要となります。作りましょう。

Snowflakeコンソールで以下クエリを実行。ネットワークルールと外部アクセス統合が作成されました。

-- Create NETWORK RULE for external access integration

CREATE OR REPLACE NETWORK RULE dbt_network_rule
  MODE = EGRESS
  TYPE = HOST_PORT
  -- Minimal URL allowlist that is required for dbt deps
  VALUE_LIST = (
    'hub.getdbt.com',
    'codeload.github.com'
    );

-- Create EXTERNAL ACCESS INTEGRATION for dbt access to external dbt package locations

CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION dbt_ext_access
  ALLOWED_NETWORK_RULES = (dbt_network_rule)
  ENABLED = TRUE;

#2-6. 「セカンダリロール」の有効化

Snowflake上のdbtプロジェクトのワークスペース内からdbtコマンドを実行するには、セカンダリロールを有効にする必要があります。

必要に応じて対象ユーザーの設定を有効化しておいてください。

ALTER USER <user_name> SET DEFAULT_SECONDARY_ROLES = ('ALL');

ちなみにユーザーに紐付くセカンダリロール情報は以下SQLで確認可能です。

--// 自分のセカンダリロール情報を確認.
SELECT CURRENT_SECONDARY_ROLES();
--// ユーザー一覧ベースでセカンダリロール情報を一括確認.
SHOW USERS;
SELECT "name", "default_secondary_roles"
  FROM TABLE(result_scan(last_query_id()));

#3. Gitリポジトリに接続されたSnowflakeワークスペースを作成

Snowflakeワークスペースでプロジェクトを作成していきます。画面左上メニュー[プロジェクト]→[ワークスペース]を選択。

ダイアログが出てきて「ワークスペースをデフォルトのSQLエディタにするかい?」と聞いてきました。ここは[今はしない]でスキップしておきます。

ワークスペースの画面全景です。

画面左上メニューの[自分のワークスペース]より[Gitリポジトリから]を選択。

必要事項を入力・選択して[作成]を押下。

  • リポジトリURL:作業対象としていたGitHubリポジトリ
  • ワークスペース名:任意。ここではチュートリアルの指示に従いtasty_bytes_dbtとしました。
  • API統合:前述手順で作成したAPI統合(TB_DBT_GIT_API_INTEGRATION)を選択。
  • アクセス方式:今回はプライベートリポジトリ経由なため個人用アクセストークンを選択。
  • 認証情報シークレット:
    • 前述手順で作成していたものを適宜指定。
    • TASTY_BYTES.DBT_DB - INTEGRATIONS - TB_DBT_GIT_SERCETの順番で指定が出来るはず。

ワークスペースの作成が出来ました!🎉

画面右上メニューから作成されたdbtプロジェクトを選択。

プロジェクト配下にあるprofiles.ymlの内容がドキュメントと同じ値で生成されているかを確認しておいてください。

#4. 環境整備のためにSQL実行(dbt実行に必要な各種データの取得・投入)

チュートリアルを進めていくうえで必要となるセットアップをSQLで行います。対象ファイルはdbtプロジェクト配下、tasty_bytes_dbt_demo/setup/tasty_bytes_setup.sqlのファイルを一部コメントアウトして実行します。

コメントアウトする箇所は計4箇所。いずれも前述までの手順で実行していた処理です。

CREATE OR REPLACE WAREHOUSE ...;
CREATE OR REPLACE API INTEGRATION ...;
CREATE OR REPLACE NETWORK RULE ...;
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION ...;

上記コメントアウトを済ませたうえで、対象ファイル内のSQLをすべて実行します。なお処理実行の際は作業過程で作成したウェアハウス:TASTY_BYTES_DBT_WHを利用しました。

(冒頭作成時にX-LARGEはデカすぎるだろと思ってX-SMALLにしましたが、処理が長引き過ぎるのもアレかなと思いひとまず1つ上げてSMALLにしました)

📙(該当箇所コメントアウト済みのSQLファイル:tasty_bytes_setup.sqlの内容はこちら)
USE ROLE accountadmin;

/**
CREATE OR REPLACE WAREHOUSE tasty_bytes_dbt_wh
    WAREHOUSE_SIZE = 'small'
    WAREHOUSE_TYPE = 'standard'
    AUTO_SUSPEND = 60
    AUTO_RESUME = TRUE
    INITIALLY_SUSPENDED = TRUE
    COMMENT = 'warehouse for tasty bytes dbt demo';
*/
USE WAREHOUSE tasty_bytes_dbt_wh;

CREATE DATABASE IF NOT EXISTS tasty_bytes_dbt_db;
CREATE OR REPLACE SCHEMA tasty_bytes_dbt_db.raw;
CREATE OR REPLACE SCHEMA tasty_bytes_dbt_db.dev;
CREATE OR REPLACE SCHEMA tasty_bytes_dbt_db.prod;


ALTER SCHEMA tasty_bytes_dbt_db.dev SET LOG_LEVEL = 'INFO';
ALTER SCHEMA tasty_bytes_dbt_db.dev SET TRACE_LEVEL = 'ALWAYS';
ALTER SCHEMA tasty_bytes_dbt_db.dev SET METRIC_LEVEL = 'ALL';

ALTER SCHEMA tasty_bytes_dbt_db.prod SET LOG_LEVEL = 'INFO';
ALTER SCHEMA tasty_bytes_dbt_db.prod SET TRACE_LEVEL = 'ALWAYS';
ALTER SCHEMA tasty_bytes_dbt_db.prod SET METRIC_LEVEL = 'ALL';

/**
CREATE OR REPLACE API INTEGRATION git_integration
  API_PROVIDER = git_https_api
  API_ALLOWED_PREFIXES = ('https://github.com/')
  ENABLED = TRUE;
*/

/**
CREATE OR REPLACE NETWORK RULE tasty_bytes_dbt_db.public.dbt_network_rule
  MODE = EGRESS
  TYPE = HOST_PORT
  VALUE_LIST = ('hub.getdbt.com', 'codeload.github.com');
*/

/**
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION dbt_access_integration
  ALLOWED_NETWORK_RULES = (tasty_bytes_dbt_db.public.dbt_network_rule)
  ENABLED = true;
*/

CREATE OR REPLACE FILE FORMAT tasty_bytes_dbt_db.public.csv_ff 
type = 'csv';

CREATE OR REPLACE STAGE tasty_bytes_dbt_db.public.s3load
COMMENT = 'Quickstarts S3 Stage Connection'
url = 's3://sfquickstarts/frostbyte_tastybytes/'
file_format = tasty_bytes_dbt_db.public.csv_ff;

/*--
 raw zone table build 
--*/

-- country table build
CREATE OR REPLACE TABLE tasty_bytes_dbt_db.raw.country
(
    country_id NUMBER(18,0),
    country VARCHAR(16777216),
    iso_currency VARCHAR(3),
    iso_country VARCHAR(2),
    city_id NUMBER(19,0),
    city VARCHAR(16777216),
    city_population VARCHAR(16777216)
) 
COMMENT = '{"origin":"sf_sit-is", "name":"tasty-bytes-dbt", "version":{"major":1, "minor":0}, "attributes":{"is_quickstart":1, "source":"sql"}}';

-- franchise table build
CREATE OR REPLACE TABLE tasty_bytes_dbt_db.raw.franchise 
(
    franchise_id NUMBER(38,0),
    first_name VARCHAR(16777216),
    last_name VARCHAR(16777216),
    city VARCHAR(16777216),
    country VARCHAR(16777216),
    e_mail VARCHAR(16777216),
    phone_number VARCHAR(16777216) 
)
COMMENT = '{"origin":"sf_sit-is", "name":"tasty-bytes-dbt", "version":{"major":1, "minor":0}, "attributes":{"is_quickstart":1, "source":"sql"}}';

-- location table build
CREATE OR REPLACE TABLE tasty_bytes_dbt_db.raw.location
(
    location_id NUMBER(19,0),
    placekey VARCHAR(16777216),
    location VARCHAR(16777216),
    city VARCHAR(16777216),
    region VARCHAR(16777216),
    iso_country_code VARCHAR(16777216),
    country VARCHAR(16777216)
)
COMMENT = '{"origin":"sf_sit-is", "name":"tasty-bytes-dbt", "version":{"major":1, "minor":0}, "attributes":{"is_quickstart":1, "source":"sql"}}';

-- menu table build
CREATE OR REPLACE TABLE tasty_bytes_dbt_db.raw.menu
(
    menu_id NUMBER(19,0),
    menu_type_id NUMBER(38,0),
    menu_type VARCHAR(16777216),
    truck_brand_name VARCHAR(16777216),
    menu_item_id NUMBER(38,0),
    menu_item_name VARCHAR(16777216),
    item_category VARCHAR(16777216),
    item_subcategory VARCHAR(16777216),
    cost_of_goods_usd NUMBER(38,4),
    sale_price_usd NUMBER(38,4),
    menu_item_health_metrics_obj VARIANT
)
COMMENT = '{"origin":"sf_sit-is", "name":"tasty-bytes-dbt", "version":{"major":1, "minor":0}, "attributes":{"is_quickstart":1, "source":"sql"}}';

-- truck table build 
CREATE OR REPLACE TABLE tasty_bytes_dbt_db.raw.truck
(
    truck_id NUMBER(38,0),
    menu_type_id NUMBER(38,0),
    primary_city VARCHAR(16777216),
    region VARCHAR(16777216),
    iso_region VARCHAR(16777216),
    country VARCHAR(16777216),
    iso_country_code VARCHAR(16777216),
    franchise_flag NUMBER(38,0),
    year NUMBER(38,0),
    make VARCHAR(16777216),
    model VARCHAR(16777216),
    ev_flag NUMBER(38,0),
    franchise_id NUMBER(38,0),
    truck_opening_date DATE
)
COMMENT = '{"origin":"sf_sit-is", "name":"tasty-bytes-dbt", "version":{"major":1, "minor":0}, "attributes":{"is_quickstart":1, "source":"sql"}}';

-- order_header table build
CREATE OR REPLACE TABLE tasty_bytes_dbt_db.raw.order_header
(
    order_id NUMBER(38,0),
    truck_id NUMBER(38,0),
    location_id FLOAT,
    customer_id NUMBER(38,0),
    discount_id VARCHAR(16777216),
    shift_id NUMBER(38,0),
    shift_start_time TIME(9),
    shift_end_time TIME(9),
    order_channel VARCHAR(16777216),
    order_ts TIMESTAMP_NTZ(9),
    served_ts VARCHAR(16777216),
    order_currency VARCHAR(3),
    order_amount NUMBER(38,4),
    order_tax_amount VARCHAR(16777216),
    order_discount_amount VARCHAR(16777216),
    order_total NUMBER(38,4)
)
COMMENT = '{"origin":"sf_sit-is", "name":"tasty-bytes-dbt", "version":{"major":1, "minor":0}, "attributes":{"is_quickstart":1, "source":"sql"}}';

-- order_detail table build
CREATE OR REPLACE TABLE tasty_bytes_dbt_db.raw.order_detail 
(
    order_detail_id NUMBER(38,0),
    order_id NUMBER(38,0),
    menu_item_id NUMBER(38,0),
    discount_id VARCHAR(16777216),
    line_number NUMBER(38,0),
    quantity NUMBER(5,0),
    unit_price NUMBER(38,4),
    price NUMBER(38,4),
    order_item_discount_amount VARCHAR(16777216)
)
COMMENT = '{"origin":"sf_sit-is", "name":"tasty-bytes-dbt", "version":{"major":1, "minor":0}, "attributes":{"is_quickstart":1, "source":"sql"}}';

-- customer loyalty table build
CREATE OR REPLACE TABLE tasty_bytes_dbt_db.raw.customer_loyalty
(
    customer_id NUMBER(38,0),
    first_name VARCHAR(16777216),
    last_name VARCHAR(16777216),
    city VARCHAR(16777216),
    country VARCHAR(16777216),
    postal_code VARCHAR(16777216),
    preferred_language VARCHAR(16777216),
    gender VARCHAR(16777216),
    favourite_brand VARCHAR(16777216),
    marital_status VARCHAR(16777216),
    children_count VARCHAR(16777216),
    sign_up_date DATE,
    birthday_date DATE,
    e_mail VARCHAR(16777216),
    phone_number VARCHAR(16777216)
)
COMMENT = '{"origin":"sf_sit-is", "name":"tasty-bytes-dbt", "version":{"major":1, "minor":0}, "attributes":{"is_quickstart":1, "source":"sql"}}';

/*--
 raw zone table load 
--*/

-- country table load
COPY INTO tasty_bytes_dbt_db.raw.country
FROM @tasty_bytes_dbt_db.public.s3load/raw_pos/country/;

-- franchise table load
COPY INTO tasty_bytes_dbt_db.raw.franchise
FROM @tasty_bytes_dbt_db.public.s3load/raw_pos/franchise/;

-- location table load
COPY INTO tasty_bytes_dbt_db.raw.location
FROM @tasty_bytes_dbt_db.public.s3load/raw_pos/location/;

-- menu table load
COPY INTO tasty_bytes_dbt_db.raw.menu
FROM @tasty_bytes_dbt_db.public.s3load/raw_pos/menu/;

-- truck table load
COPY INTO tasty_bytes_dbt_db.raw.truck
FROM @tasty_bytes_dbt_db.public.s3load/raw_pos/truck/;

-- customer_loyalty table load
COPY INTO tasty_bytes_dbt_db.raw.customer_loyalty
FROM @tasty_bytes_dbt_db.public.s3load/raw_customer/customer_loyalty/;

-- order_header table load
COPY INTO tasty_bytes_dbt_db.raw.order_header
FROM @tasty_bytes_dbt_db.public.s3load/raw_pos/order_header/;

-- order_detail table load
COPY INTO tasty_bytes_dbt_db.raw.order_detail
FROM @tasty_bytes_dbt_db.public.s3load/raw_pos/order_detail/;

-- setup completion note
SELECT 'tasty_bytes_dbt_db setup is now complete' AS note;

ウェアハウスサイズ:SMALLでおおよそ5分程度掛かり、処理がすべて終了。

ログ・トレース・メトリクスが有効になっていることを確認します。

設定に該当するSQLはこちら。ちなみに上記一括SQLで既に実行されています。検証環境(dev)、本番環境(prod)それぞれに設定が為されています。

ALTER SCHEMA tasty_bytes_dbt_db.dev SET LOG_LEVEL = 'INFO';
ALTER SCHEMA tasty_bytes_dbt_db.dev SET TRACE_LEVEL = 'ALWAYS';
ALTER SCHEMA tasty_bytes_dbt_db.dev SET METRIC_LEVEL = 'ALL';

ALTER SCHEMA tasty_bytes_dbt_db.prod SET LOG_LEVEL = 'INFO';
ALTER SCHEMA tasty_bytes_dbt_db.prod SET TRACE_LEVEL = 'ALWAYS';
ALTER SCHEMA tasty_bytes_dbt_db.prod SET METRIC_LEVEL = 'ALL';

確認用SQLは以下。適宜設定されている内容が正しいかどうか確認してみてください。

SHOW PARAMETERS LIKE 'log_level' IN SCHEMA tasty_bytes_dbt_db.dev;
SHOW PARAMETERS LIKE 'trace_level' IN SCHEMA tasty_bytes_dbt_db.dev;
SHOW PARAMETERS LIKE 'metric_level' IN SCHEMA tasty_bytes_dbt_db.dev;

SHOW PARAMETERS LIKE 'log_level' IN SCHEMA tasty_bytes_dbt_db.prod;
SHOW PARAMETERS LIKE 'trace_level' IN SCHEMA tasty_bytes_dbt_db.prod;
SHOW PARAMETERS LIKE 'metric_level' IN SCHEMA tasty_bytes_dbt_db.prod;

これで必要な環境、情報が揃いました!

次の項からは実際にdbt Projects on Snowflake上で色々な操作をしてみます。

#5. dbtプロジェクトでdbt depsコマンドを実行

ここからはdbtプロジェクトで通常行われる各種処理実行を「dbt Project on Snowflake」でどう実行するのか...的な視点でそれぞれの手順を見ていきます。
基本的には、dbtで行っていた各種操作(dbt deps, dbt test等)はワークスペース上部のメニューからそれぞれ必要な操作を選択して実行ボタンを押す形で行います。

まずはdbt depsコマンドの実行から。

画面右下の[出力]タブを選択し、ワークスペースからdbtコマンドを実行した後の標準出力を表示できるようにしておきます。

プロジェクトが当作業で作成されたものであることを確認し、画面上部のプロファイル指定などを確認、指定していきます。今回はそのままプロファイル=devで作業を進めることが出来ました。

[依存関係]を選択して[実行(横向き三角)]ボタンを押下。

前述手順で作成した外部アクセス統合を選択し、[依存関係]押下。

程なくして処理が完了しました。

ファイルpackage_lock.ymlが作成、ワー​​クスペースのファイルリストに「A」の横に表示されました。

packages:
  - package: dbt-labs/dbt_utils
    version: 1.3.0


あれ、想定とちょっと違う

#6. コンパイル

対象となるプロジェクト、プロファイルを選択した上で画面上部メニューのアクションプルダウンから[コンパイル]を選択し、実行。(実行ボタン右側のメニューからオプション指定実行も可能です)

実行完了。

ワークスペース下部のエディタ領域にて、コンパイル結果をもとにしたDAG(Directed Cyclic Graph/有向循環グラフ、ノードが互いに方向性を持って関連し、方向性のある閉ループを形成しないグラフ)を参照することが出来ます。DAGは分析エンジニアリングの実務において、データモデル間の関係性を視覚的に表現するためによく使用されます。

DAGではソースデータであったり、

ソースから生成された各種モデルの情報をたどることが出来ます。

モデルについては[コンパイルされたSQLを表示]を選択する事で、

コンパイル済のSQLを並列表示させることも出来ます。

#7. プロジェクト実行(dbt run)

対象となるプロジェクト、プロファイルを選択した上で画面上部メニューのアクションプルダウンから[実行]を選択し、実行。

出力ペインに実行結果が出力されます。問題なく実行出来ました。

実行結果を確認するためにSQLを実行します。examples/フォルダ配下にSQLファイルを作成。

名前はdbt_sandbox.sqlとしました。

テーブル一覧とビュー一覧を確認するSQLをそれぞれ実行。内容を確認出来ました。

SHOW TABLES IN DATABASE tasty_bytes_dbt_db;

SHOW VIEWS IN DATABASE tasty_bytes_dbt_db;

#8. 変更を反映

ワークスペース画面左上の[変更]→[main]を選択。ここまでの一連の変更内容(リポジトリへは未反映)が諸々確認出来ます。この内容をリポジトリに反映させましょう。[プッシュ]を選択。ここは一旦mainブランチにそのまま行っちゃいました。

コメントを記載の上プッシュ実行。

プッシュ完了です。内容をGitリポジトリ側でも確認しておいてください。

※ちなみにブランチをそれぞれ切ってプッシュすることも勿論可能です。

#9. テストの実施(dbt test)

変更を反映させた後に変更が発生するトピックになっちゃってアレなんですが、dbtのテスト(dbt test)についても試してみました。画面上部メニューからテスト実行。

暫し待機。ところがエラーでコケました。どうやらリポジトリで作成されていたテストについて、1箇所エラーとなる形になっていたようです。

内容を確認したところ、あるカラムのテストについて範囲指定をしていた箇所、実際のデータがこの範囲を超えるものが(多数)存在していたことが原因となっていました。(本来どうかと思うけど)ひとまずここはテストNGを解消させたいのでテスト側の範囲指定を緩和しました(本当はどうかと思うけど)。

テスト再実行。今度は通りました(そりゃそうだ)。改めてここまでの変更をGitリポジトリに反映しておきました。(こっちはブランチを切って対処)

#10. デプロイ

ワークスペースからdbtプロジェクトをデプロイしてdbtプロジェクトオブジェクトを作成します。このオブジェクトを使用して、ワークスペース外のSnowflakeでdbtプロジェクトのスケジュール設定、実行、監視を行うことが出来るようになります。

画面右上メニューの[接続]から[dbtプロジェクトをデプロイ]を選択。

場所の指定(スキーマはdev指定でOK)、[dbtプロジェクトを作成]を選択、任意のプロジェクト名(今回はTASTY_BYTES_DBT_PROJECTとしました)を入力し、[展開]を押下。

デプロイが完了しました。

CREATE DBT PROJECT "TASTY_BYTES_DBT_DB"."DEV"."TASTY_BYTES_DBT_PROJECT" FROM 'snow://workspace/USER$xxxxxxxxxxxxxxxxx.PUBLIC."tasty_bytes_dbt"/versions/live/tasty_bytes_dbt_demo'

TASTY_BYTES_DBT_PROJECT が正常に作成されました。

画面右上メニューを再度展開。[プロジェクトを表示]を選択。

画面が切り替わり、データベースエクスプローラーから対象のdbtプロジェクトが表示されるようになりました。

また、`SHOW DBT PROJECTS'コマンドでプロジェクトの情報をSQLベースで確認出来るようになりました。

SHOW DBT PROJECTS LIKE 'tasty%';

#11. スケジュール実行(dbtプロジェクト実行のタスクを作成)

dbtプロジェクトに対する各種実行させたい処理を、Snowflakeのタスクを介して設定・実行する手順を行います。画面右上メニューから[スケジュールを作成]を選択。

実行させたいスケジュールを設定します。ここでは`dbt run'をオプション指定で毎時40分(タイムゾーンはJST)に実行させるという設定を作成する事にしました。[作成]押下。

内容を確認し、[完了]押下。

Snowflakeの要素(タスク)として作成されていることも確認出来ています。

所定の時間が来たのでSnowflakeのタスクとして実行されているかどうかを見てみます。

ちゃんと実行されていることが確認出来ました!

CREATE OR REPLACE TASK tasty_bytes_dbt_db.dev.run_prepped_data_dbt
        WAREHOUSE=tasty_bytes_dbt_wh
        SCHEDULE ='USING CRON 1 * * * * America/Los_Angeles'
      AS
  EXECUTE DBT PROJECT tasty_bytes_dbt_project ARGS='run --select customer_loyalty_metrics --target dev';

このままにしておくと毎時タスクとして実行してしまうので一旦設定を無効化しておきます。画面右上の三点リーダメニューから[編集]を選択。

内容を確認の上、

スケジュールを無効化し、[保存]を押下。

タスクとしては残った状態ですが、時間指定の部分の設定がなくなっていることが確認出来ました。

#12. リソースのお掃除

以上でdbt Project on Snowflakeに関するチュートリアルの一連の作業は終わりとなります。お疲れ様でした!

リソースを削除する場合は以下のDROP文をそれぞれ実行し、

DROP WAREHOUSE IF EXISTS tasty_bytes_dbt_wh;
DROP DATABASE IF EXISTS tasty_bytes_dbt_db;
DROP DATABASE IF EXISTS tb_101;

プロジェクトワークスペースの左上メニュー、プロジェクト名の右横にある三点リーダーメニューから[削除]を行っておいてください。

個人的にははまだ色々試してみたいので削除はせずそのままにしています

まとめ

という訳でチュートリアル『dbt Project on Snowflake』の実践内容紹介エントリでした。初設定を済ませてしまえばdbt Cloud環境で操作するが如くプロジェクトを動かすことが出来るのは本当に便利ですね。現状幾つか制約はあるとは思いますが十分に実用に足る、使い勝手の良さそうな機能だと思います。今後も色々なケース、色々な側面を検証しつつ使い倒していきたいと思います!

Discussion