dbt Projects on Snowflake で dbt_semantic_view パッケージを使い Semantic View の作成からマテリアライゼーション管理までやってみた

dbt Projects on Snowflake で dbt_semantic_view パッケージを使い Semantic View の作成からマテリアライゼーション管理までやってみた

Snowflake-Labsの dbt_semantic_view パッケージを dbt Projects on Snowflake で試してみました。Semantic Viewの作成から下流モデルの参照、マテリアライゼーションの宣言的な管理まで、実装と検証結果をまとめます。
2026.11.11

かわばたです。

本記事では、Snowflake-Labs が公開している dbt パッケージ dbt_semantic_view を dbt Projects on Snowflake で使います。Snowsight の Workspace から Semantic View の作成、下流モデルからの参照、マテリアライゼーションの宣言的な管理までを検証します。

https://hub.getdbt.com/Snowflake-Labs/dbt_semantic_view/latest/

https://github.com/Snowflake-Labs/dbt_semantic_view

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

dbt_semantic_view パッケージの概要

dbt_semantic_view は Snowflake-Labs が Apache-2.0 で公開している dbt パッケージです。

追加されるのは materialized='semantic_view' という materialization です。モデルの SQL ファイルに CREATE SEMANTIC VIEW の TABLES 句以降をそのまま書き、テーブル名の位置に ref() や source() を置きます。dbt は先頭に CREATE OR REPLACE SEMANTIC VIEW <モデル名> を付けて実行します。Snowflake の SQL をそのまま通す作りなので、新しい句が増えてもパッケージの更新を待たずに使えます。config は次の 4 つです。

config 既定値 働き
copy_grants false CREATE OR REPLACE の末尾に COPY GRANTS を付ける
create_or_alter false CREATE OR REPLACE の代わりに CREATE OR ALTER を使う
max_staleness なし 末尾に MAX_STALENESS = '<値>' を付ける。マテリアライゼーションには MAX_STALENESS が必要で、config か SQL 本文のどちらか一方で指定する
sv_materializations なし マテリアライゼーションの YAML 定義。run のたびに SYSTEM$MANAGE_SEMANTIC_VIEW_MATERIALIZATIONS_FROM_YAML で同期する

このほか、generic test が 2 つ付属します(materialization_exists、materialization_is_active)。マテリアライゼーションの有無と状態を確かめるものです。persist_docs には対応していません。

dbt Projects on Snowflake で使えるか

パッケージの中身は Jinja マクロだけで、Python や他パッケージへの依存はありません。custom materialization は dbt Core の標準機構なので、Snowflake が管理する dbt Core ランタイムでそのまま動きます。制限事項のページにも、custom materialization やパッケージを制限する記載はありません。事前に押さえる点は 2 つです。

  • Snowflake 内の dbt deps で dbt Hub からパッケージを取るには External Access Integration が必要です。trial アカウントでは external access が既定で無効のため、本記事はパッケージを local package として置きます
  • dbt Fusion(2.x)ランタイムでは、create_or_alter などの config キーが拒否されます

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

本記事は dbt Core 1.12.3 で進めます。

前提条件

  • dbt Projects on Snowflake と Semantic View が使えるアカウント。エディション要件は記載がなく、trial アカウント(Business Critical と Enterprise)で確認しています
  • dbt の実行ロールに、対象スキーマの CREATE SEMANTIC VIEW、ADD SEMANTIC VIEW MATERIALIZATION、CREATE DBT PROJECT
  • 同じロールに、ウェアハウスの USAGE と SNOWFLAKE_SAMPLE_DATA の参照権限
  • Semantic View のマテリアライゼーションはプレビュー機能です(全アカウントで利用可)。MAX_STALENESS の最小値は 120 秒です

2026年10月29日に AWS 東京リージョンの trial アカウントで検証しました。generic test と Fusion の挙動は、2026年11月11日に別の trial アカウントで追加確認しました。
dbt コマンドは Snowsight の Workspace で実行し、ランタイムは dbt Core 1.12.3(dbt-snowflake 1.12.0)です。

事前準備

Snowflake 側のオブジェクト

ACCOUNTADMIN で実行ロール、DB とスキーマ、ウェアハウスを作り、必要な権限を個別に付けます。ADD SEMANTIC VIEW MATERIALIZATION は、マテリアライゼーションを追加・削除するためのスキーマ権限です。

USE ROLE ACCOUNTADMIN;

CREATE ROLE DBT_SV_ROLE;
GRANT ROLE DBT_SV_ROLE TO ROLE SYSADMIN;
GRANT ROLE DBT_SV_ROLE TO USER <自分のユーザー名>;

CREATE WAREHOUSE DBT_SV_WH WAREHOUSE_SIZE = XSMALL AUTO_SUSPEND = 60 INITIALLY_SUSPENDED = TRUE;
CREATE DATABASE DBT_SV_DB;
CREATE SCHEMA DBT_SV_DB.DEV;

GRANT USAGE ON WAREHOUSE DBT_SV_WH TO ROLE DBT_SV_ROLE;
GRANT USAGE ON DATABASE DBT_SV_DB TO ROLE DBT_SV_ROLE;
GRANT USAGE, CREATE TABLE, CREATE VIEW, CREATE SEMANTIC VIEW, ADD SEMANTIC VIEW MATERIALIZATION,
      CREATE DBT PROJECT, CREATE STAGE, CREATE TASK ON SCHEMA DBT_SV_DB.DEV TO ROLE DBT_SV_ROLE;
GRANT EXECUTE TASK ON ACCOUNT TO ROLE DBT_SV_ROLE;
GRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE_SAMPLE_DATA TO ROLE DBT_SV_ROLE;

パッケージの置き方

Snowflake 内の dbt deps で dbt Hub からパッケージを取るには External Access Integration が必要です。許可先は hub.getdbt.com と codeload.github.com で、デプロイ時に指定します。
trial アカウントでは external access が既定で無効で、有効化には担当者への依頼が必要です。今回の環境ではネットワークルールは作れましたが、External Access Integration の作成がエラーになりました。

本記事はパッケージのソースを local_packages/ に置く local package 方式を使います。Snowflake 側の dbt deps がネットワークなしで通るため、Workspace だけで完結します。

dbt プロジェクト

Workspace に置くプロジェクトは次の構成です。seed は使わず、SNOWFLAKE_SAMPLE_DATA の TPCH_SF1 を source にします。

dbt_sv_demo/
├── dbt_project.yml
├── profiles.yml
├── packages.yml
├── local_packages/dbt_semantic_view/     # GitHub v1.0.6 の dbt_project.yml、LICENSE、macros/ だけをコピー
└── models/
    ├── sources.yml                       # tpch: SNOWFLAKE_SAMPLE_DATA.TPCH_SF1 の orders / customer
    ├── staging/stg_orders.sql, stg_customers.sql
    ├── semantic/sv_tpch_sales.sql, schema.yml
    └── marts/revenue_by_segment_year.sql

local_packages/dbt_semantic_view/ に必要なのは dbt_project.yml、LICENSE、macros/ の 3 つだけです。integration_tests/ や docs/ は不要で、プロジェクト全体は 18 ファイルに収まります。packages.yml は local 参照にします。

packages:
  - local: local_packages/dbt_semantic_view

dbt Projects on Snowflake では profiles.yml をプロジェクトのルートに置きます。実行は Snowflake 内で行われるため、account と user はプレースホルダーで構いません。

dbt_sv_demo:
  target: dev
  outputs:
    dev:
      type: snowflake
      account: "_"
      user: "_"
      role: DBT_SV_ROLE
      database: DBT_SV_DB
      schema: DEV
      warehouse: DBT_SV_WH
      threads: 4

dbt_project.yml では staging と marts を +materialized: table にします。staging モデルは TPCH の列名を揃えるだけです。

-- models/staging/stg_orders.sql
select
    o_orderkey      as order_key,
    o_custkey       as customer_key,
    o_orderdate     as order_date,
    o_orderstatus   as order_status,
    o_orderpriority as order_priority,
    o_totalprice    as order_total
from {{ source('tpch', 'orders') }}

stg_customers.sql も同様です。c_custkey は customer_key、c_name は customer_name、c_mktsegment は market_segment にします。

試してみた

Workspace にプロジェクトを置いて dbt deps を実行する

Snowsight の Projects » Workspaces で Workspace を作り、上のファイルを配置します。dbt のランタイムはアカウントの既定値から 1.12.3 に変えておきます。

続けて dbt deps を実行します。パッケージは local_packages/ にあるので、ネットワークを使わずに dbt_packages/dbt_semantic_view/ が作られます。

Semantic View のモデルを作って dbt build

models/semantic/sv_tpch_sales.sql を作ります。まずはマテリアライゼーションなしの基本形です。TPCH の orders と customer を論理テーブルにし、ディメンション 5 つとメトリクス 3 つを定義します。

{{ config(materialized='semantic_view') }}

TABLES (
    orders    AS {{ ref('stg_orders') }}    PRIMARY KEY (order_key)    COMMENT = 'TPC-H orders',
    customers AS {{ ref('stg_customers') }} PRIMARY KEY (customer_key) COMMENT = 'TPC-H customers'
)
RELATIONSHIPS (
    orders_to_customers AS orders (customer_key) REFERENCES customers (customer_key)
)
FACTS (
    orders.order_total AS order_total COMMENT = 'Order total price'
)
DIMENSIONS (
    orders.order_date        AS order_date,
    orders.order_year        AS YEAR(order_date),
    orders.order_status      AS order_status,
    customers.customer_name  AS customer_name,
    customers.market_segment AS market_segment
)
METRICS (
    orders.total_revenue       AS SUM(order_total)  COMMENT = 'Sum of order total price',
    orders.order_count         AS COUNT(order_key)  COMMENT = 'Number of orders',
    orders.average_order_value AS AVG(order_total)  COMMENT = 'Average order total price'
)
COMMENT = 'TPC-H sales semantic view managed by dbt'

dbt build を実行すると、staging の 2 テーブルに続いて Semantic View が作られます。ログには semantic_view model として表示されます。

dbt が発行した DDL は Query History で確認できます。

Semantic View に問い合わせると、5 つのセグメントごとの売上と件数が 5 行返ります。

SELECT *
FROM SEMANTIC_VIEW(
    DBT_SV_DB.DEV.SV_TPCH_SALES
    METRICS    orders.total_revenue, orders.order_count
    DIMENSIONS customers.market_segment
)
ORDER BY market_segment;

下流モデルから参照して DAG を見る

Semantic View を ref() で参照する下流モデルを追加します。semantic_view() 関数の中で ref() を使うだけです。

-- models/marts/revenue_by_segment_year.sql
select *
from semantic_view(
    {{ ref('sv_tpch_sales') }}
    metrics    orders.total_revenue, orders.order_count
    dimensions customers.market_segment, orders.order_year
)
order by market_segment, order_year

マテリアライゼーションを宣言的に追加する

https://docs.snowflake.com/en/release-notes/2026/10_24

Semantic View のマテリアライゼーションは、2026年7月15日に Public Preview になりました。よく使うディメンションとメトリクスの組み合わせを事前集計しておく仕組みです。素の SQL では ALTER SEMANTIC VIEW ... ADD MATERIALIZATION で 1 つずつ追加します。パッケージでは YAML で「あるべき状態」を書き、run のたびに同期します。

https://docs.snowflake.com/en/user-guide/views-semantic/materializations

sv_tpch_sales.sql の先頭を次のように変えます。ウェアハウス名を target から取るため YAML は {% set %} で組み立て、create_or_alter=true と max_staleness も同時に指定します。

{%- set sv_mats_yaml -%}
materializations:
  - name: mat_revenue_by_segment_year
    warehouse: {{ target.warehouse }}
    dimensions:
      - table: customers
        name: market_segment
      - table: orders
        name: order_year
    metrics:
      - table: orders
        name: total_revenue
      - table: orders
        name: order_count
{%- endset -%}

{{ config(
    materialized='semantic_view',
    create_or_alter=true,
    max_staleness='1 hour',
    sv_materializations=sv_mats_yaml
) }}

TABLES (
    ...(本文は変更なし)

dbt run --select sv_tpch_sales を実行すると、dbt は 2 文を続けて発行します。
SHOW MATERIALIZATIONS IN SEMANTIC VIEW を見ると、MAT_REVENUE_BY_SEGMENT_YEAR が 1 行入っています。

state は ACTIVE、warehouse は DBT_SV_WH、refresh_mode は FULL です。refresh_mode_reason 列によると実体は dynamic table で、2 つの論理テーブルをまたぐ集計のため AUTO が FULL に解決されています。

再実行・定義変更・CREATE OR REPLACE の違い

同じ定義で再度 run しても、戻り値は「Added/replaced: 1」のままです。ただし作り直しは起きていません。stale_by は途切れずに増え続け、リフレッシュ履歴に FULL は増えませんでした。

戻り値の数字は YAML に書いた件数で、変更の有無を示すものではないと読むのが妥当です。YAML の dimensions に orders.order_status を足して run すると、run の 2 秒後にリフレッシュ履歴へ FULL の行が追加されました。stale_by も 16s に戻りました。同じ定義で再 run したときには追加されなかったので、定義変更で作り直されたと判断できます。

CREATE OR REPLACE は既存のマテリアライゼーションを削除します。本構成では直後の YAML 同期が作り直すため、run のたびに初期化(フルリフレッシュ)の計算コストがかかります。これを避けるため create_or_alter=true を前提にします。

generic test でマテリアライゼーションの状態を確認する

パッケージ付属の generic test を models/semantic/schema.yml に書きます。README の例では引数を test 名の直下に書いていますが、dbt Core 1.12.3 では非推奨の警告になり、dbt Fusion ではエラー(dbt1159)になります。arguments: の下に入れます。

version: 2

models:
  - name: sv_tpch_sales
    tests:
      - dbt_semantic_view.materialization_exists:
          arguments:
            materialization_name: mat_revenue_by_segment_year
      - dbt_semantic_view.materialization_is_active:
          arguments:
            materialization_name: mat_revenue_by_segment_year

arguments: は dbt Core 1.10.5 以降の書き方です。dbt 1.9.4 のままだと arguments が test マクロへの引数として渡され、コンパイルエラーになります。メッセージは macro 'dbt_macro__test_materialization_exists' takes no keyword argument 'arguments' です。

2 つのテストは SHOW MATERIALIZATIONS の結果を読みます。materialization_exists は名前の有無を、materialization_is_active は state が SUSPENDED でないことを確かめます。dbt test を実行すると 2 つとも PASS します。

次にマテリアライゼーションを手で止めて、テストが検知するかを見ます。

ALTER SEMANTIC VIEW DBT_SV_DB.DEV.SV_TPCH_SALES SUSPEND MATERIALIZATION MAT_REVENUE_BY_SEGMENT_YEAR;
SHOW MATERIALIZATIONS IN SEMANTIC VIEW DBT_SV_DB.DEV.SV_TPCH_SALES;

state が SUSPENDED、suspend_reason が「The materialization was suspended by a user」になります。この状態で dbt test を実行すると、materialization_is_active だけが失敗します。

RESUME MATERIALIZATION で戻すと ACTIVE に戻り、もう一度 dbt test を実行すると 2 PASS に戻ります。stale_by は止める前からの時間を引き継ぎ、作り直しは起きません。

ALTER SEMANTIC VIEW DBT_SV_DB.DEV.SV_TPCH_SALES RESUME MATERIALIZATION MAT_REVENUE_BY_SEGMENT_YEAR;

dbt Fusion 2.0.0 で実行してみる

dbt Projects on Snowflake は dbt Fusion(2.x)も選べます。
結論から書くと、Fusion でも Semantic View の作成はできます。使えないのは create_or_alter と sv_materializations によるマテリアライゼーション管理です。

Workspace の実行が内部で使っている EXECUTE DBT PROJECT FROM WORKSPACE を SQL ファイルから実行します。DBT_VERSION で 2.0.0 を指定します。

EXECUTE DBT PROJECT FROM WORKSPACE "USER$KAWABATA"."PUBLIC"."dbt_sv_demo"
  ARGS = 'parse'
  DBT_VERSION = '2.0.0';

マテリアライゼーションの config を付けたモデルは、parse の段階で 2 件のエラーで止まりました。GitHub issue #34 の報告どおりです。

Fusion は config の検証が厳しく、未知のキーをエラーにします。dbt Core 1.12.3 では同じキーが CustomKeyInConfigDeprecation の警告で済んでいました。パッケージが config.get() でキーを読む作りのため、利用者が meta へ移しても回避できません。

一方、config が materialized='semantic_view' だけの基本形モデルは、Fusion 2.0.0 でも dbt run が成功しました。本文が SELECT 文ではないため SyntaxInvalid (dbt0101) の警告が出ますが、実行には影響しません。

カスタム指示も本文に書ける

パッケージは本文を DDL にそのまま渡します。そのため、CREATE SEMANTIC VIEW で書ける句はそのまま使えます。カスタム指示(AI_SQL_GENERATION、AI_QUESTION_CATEGORIZATION)も同じです。AI_VERIFIED_QUERIES や WITH SYNONYMS も書けます。

COMMENT = 'TPC-H sales semantic view managed by dbt'
AI_SQL_GENERATION 'If no time period is specified, filter to the last 7 days.'
AI_QUESTION_CATEGORIZATION 'Reject questions about individual customers.'

制限事項・注意点

2026年11月11日時点の挙動と、パッケージの GitHub issue で報告されている内容です。

制限事項・注意点
  • dbt Fusion 2.0.0 では、create_or_alter と sv_materializations が UnusedConfigKey(dbt1060)で拒否されます。issue #34 の報告どおりで、Hub の Fusion 互換バッジは parse の機械判定です。基本形の Semantic View モデルは Fusion でも動きます
  • trial アカウントでは external access が既定で無効です(担当者への依頼で有効化できます)。今回の環境では External Access Integration の作成が 509009 で失敗しました。Hub パッケージは local package にするか、CLI からローカルで dbt deps を済ませて dbt_packages/ を同梱します
  • dbt Core 1.9 系では作成後の introspection エラーの報告があります(issue #5)。1.12.3 では出ませんでしたが、trial の既定は 1.9.4 なのでバージョンを明示してください
  • persist_docs は非対応です(README に記載)。説明は DDL の COMMENT 句に書きます。--empty フラグも使えません(issue #11)
  • sv_materializations の filter_clause は、ストアドプロシージャ経由では効果がないという報告があります(issue #35)。refresh_mode も無視されます。使うなら ALTER SEMANTIC VIEW ... ADD MATERIALIZATION を post_hook に書きます。ただし同期プロシージャは YAML に無いマテリアライゼーションを削除します。その Semantic View では sv_materializations を使わず、管理を post_hook 側に統一してください
  • ストアドプロシージャの戻り値「Added/replaced: N」は、定義が同じでも YAML の件数を返します。作り直しの有無は stale_by かリフレッシュ履歴で判断してください
  • COPY GRANTS は CREATE OR ALTER と併用できません。CREATE OR ALTER には Semantic View の OWNERSHIP が必要で、タグの変更もできません。generic test の引数は arguments: の下に書きます
  • マテリアライゼーションはプレビュー機能で、効果があるのは SEMANTIC_VIEW() や標準 SQL で Semantic View を経由するクエリだけです。Cortex Analyst や Cortex Agent のように基になる物理テーブルへ直接 SQL を発行するクエリには使われません。マテリアライゼーションがある間は MAX_STALENESS を解除できません

最後に

dbt_semantic_view パッケージは Jinja マクロだけでできているため、dbt Projects on Snowflake の dbt Core 1.12.3 でそのまま動きました。Semantic View と下流モデルを同じ DAG に載せられ、マテリアライゼーションも YAML で冪等に同期できます。Fusion ランタイムでも Semantic View の作成は動きます。マテリアライゼーション管理の config は検証で止まるため、こちらを使うなら当面は dbt Core を選ぶのが確実です。

この記事が何かの参考になれば幸いです!


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

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

Snowflakeの詳細を見る

この記事をシェアする

関連記事