はじめに

こんにちは。全社データ技術局データビジュアライゼーションチームの與田龍人です。

モダンデータスタックにおいて、「セマンティックレイヤー」は実務上の必須要件になりつつあります。売上、コスト、アクティブユーザー数 — こうしたビジネス指標の定義を一元化し、誰がどのツールから見ても同じ数字が返ってくる状態が理想です。

しかし現実には、Snowflake、dbt、Tableau、Looker、Power BI… 各社が独自のセマンティックレイヤーを持っていて、同じ指標を複数箇所にメンテナンスしている状況が多いのではないでしょうか。この二重管理を解消する一つの選択肢として、上流であるDWH側のセマンティック定義を、BIなどの可視化ツールにAPIで渡すというアプローチがあります。DWHを「定義の源泉」として扱い、下流のツールにはそれを変換して同期する — こうすることで、メンテナンス箇所を1つに絞ることができます。

本記事では、Snowflake Semantic Viewで定義したセマンティック情報を、Tableau Semantics Authoring APIに変換して同期する「セマンティックゲートウェイ」的な仕組みを紹介します。今回はTableau Next上での可視化をメインに行いましたが、Tableau Semanticsを利用するTableau Cloud・CRM Analyticsなど、Salesforceエコシステム全体に適用できるアプローチです。

セマンティックレイヤーの現状

各社のセマンティックレイヤー

主要プラットフォームのセマンティックレイヤーを整理すると以下の通りです。

プラットフォーム セマンティックレイヤー 定義形式
Snowflake Semantic View SQL DDL
dbt Semantic Layer (MetricFlow) YAML
Tableau / Salesforce Tableau Semantics REST API (JSON)
Looker LookML LookML
Databricks Metric View SQL / API
Power BI Semantic Model TMDL / XMLA

例えば「月次売上」を定義するとき、Snowflakeで SUM(revenue) と書き、dbtのYAMLにも type: sum と書き、Tableau Semantics でも aggregationType: Sum を設定する、ということが起きます。

標準化の動き: Open Semantic Interchange (OSI)

この分断に対して、業界全体での標準化も進んでいます。2026年1月に公開された Open Semantic Interchange (OSI) v1.0 は、Snowflake・dbt・Databricksなど30以上のベンダーが支持するセマンティックレイヤーの標準規格です。

ただし、OSIは策定段階であり各BIツールのネイティブサポートはまだ限定的です。本記事では、今ある手段で解決できる実装寄りのアプローチを紹介します。

前回の記事から

以前、dbt × Snowflake Semantic View × Cortex Analyst でセマンティックレイヤーを構築する記事を書きました。

dbt (データマート作成) → Snowflake Semantic View (定義) → Cortex Analyst (AI自然言語分析)

dbtの dbt_semantic_view パッケージで、データマートを作った流れでそのままSemantic Viewを定義し、Cortex Analystで自然言語分析できるところまで実現しました。

残っていた課題: BIツール側のセマンティックレイヤーには、同じ定義を手動で作り直す必要がありました。

今回のアプローチ: APIでセマンティック定義を渡す

なぜdbtのセマンティックレイヤーを使わないのか

dbtにはMetricFlowベースのセマンティックレイヤーがあります。今回はこれを使わず、Snowflake Semantic Viewに寄せています。理由は以下の通りです。

dbtから直接作れるdbt_semantic_view パッケージでデータマートと同じパイプラインで定義できます。

Cortex Analystにも使える — AI分析とBI分析の両方で同じ定義を使い回せます。

DESCRIBE SEMANTIC VIEW で定義を取得できる — プログラムから読み取り可能なので、他のシステムに渡しやすいです。

両者の違いを整理すると以下の通りです。

dbt Semantic Layer Snowflake Semantic View
定義形式 YAML (MetricFlow) SQL DDL
実行環境 dbt Cloud / dbt Core Snowflake ネイティブ
BIとの連携 dbt Cloud経由(対応ツール限定) DESCRIBE で定義取得 → API転送が可能
AI連携 Cortex Analyst対応
コスト dbt Cloud課金が必要 Snowflake内で完結

個人的には、dbtはデータ変換とモデリングの役割に集中してもらい、セマンティック定義の「保管場所」はSnowflakeに任せるのが現実的だと考えています。dbtの dbt_semantic_view パッケージを使えば、dbtのパイプラインの中でSemantic Viewを定義できるので、ワークフローとしてもきれいに収まります。

アーキテクチャ


ポイントは以下の通りです。

定義はSnowflake Semantic Viewの1箇所だけ。dbt → Semantic View の流れでコードレビュー・バージョン管理が効きます。Tableau Semanticsを使うサービス(Tableau Next、Tableau Cloud、CRM Analytics)すべてに反映されます。

実装の詳細

今回は、Snowflake上で管理している寿司の販売サンプルデータを例に使います。商品名・地域・チャネルといったディメンションと、売上金額・販売数量といったメジャーを持つテーブル(SUSHI_SALES)に対してSemantic Viewを定義し、Tableau Semanticsに同期する流れを見ていきます。

概念マッピング

Snowflakeのセマンティック概念は、以下のようにTableau Semanticsの概念に対応させています。

Snowflake Tableau Semantics 説明
DIMENSION Dimension グループ化・フィルタ軸 (VARCHAR → Discrete, DATE → Continuous)
FACT Measure 集計対象の数値 (NUMBER/FLOAT → Continuous, Sum)
METRIC Metric 事前定義された集計式 (SUM等 + 時間軸 + Insights設定)

実際のセマンティックビュー画面

sv_snowflake

1. Snowflake Semantic View の定義を読み取る

DESCRIBE SEMANTIC VIEW を実行すると、フラットな行データで定義が返ってきます。これを object_kindobject_name でグルーピングして、フィールド単位の辞書に変換します。今回のSUSHIデータの場合、以下のような結果が得られます。

object_kind object_name property property_value
DIMENSION ITEM_NAME COMMENT 商品名
FACT REVENUE DATA_TYPE NUMBER(38,2)
METRIC TOTAL_REVENUE EXPRESSION SUM(SUSHI_SALES.REVENUE)

Lambdaではこの結果をパースして、DIMENSION/FACT/METRICをそれぞれリストに振り分けます。Semantic Viewにどんなフィールドを定義しても同じロジックで処理できるようになっています。

2. 型変換と命名規則

Snowflakeの型(VARCHAR, NUMBER, DATE 等)は、Tableau Semantics側の型に自動変換されます。また、フィールド名はテーブル名をプレフィックスとして付与する命名規則に従います。

今回のSUSHIデータの場合、以下のように変換されます。

Snowflake側 Tableau Semantics側
ITEM_NAME (VARCHAR) SUSHI_SALES_ITEM_NAME (Text)
SALE_DATE (DATE) SUSHI_SALES_SALE_DATE (Date)
REVENUE (NUMBER) SUSHI_SALES_REVENUE (Number)

DLOのフィールド名は {column小文字}__c(例: revenue__c)、メトリクスは {column}_mtc(例: REVENUE_mtc)の形式で自動生成されます。

3. Tableau Semantics Authoring API を呼ぶ

Salesforce REST APIに対して3段階でPOSTします。認証はJWT Bearer Flowです。以下はLambdaが実際に生成するペイロードの構造です。

3-1. セマンティックモデルの作成

sf_request("POST", "/services/data/v66.0/ssot/semantic/models", token_info, {
    "apiName": model_name,          # Semantic View名から自動導出
    "label": model_name,
    "dataspace": "default",
    "queryUnrelatedDataObjects": "Union",
    "sourceCreation": "DataCloud",  # CLIデプロイ互換に必須
})

3-2. データオブジェクト + フィールドを一括作成

Semantic Viewで定義したDIMENSION/FACTから、ディメンションとメジャーのフィールド定義を自動生成してPOSTします。

sf_request("POST", f"{api}/{model_name}/data-objects", token_info, {
    "apiName": base_table,                     # テーブル名がそのままAPI名
    "label": base_table,
    "dataObjectName": f"{base_table}__dll",    # DLO参照
    "dataObjectType": "Dlo",
    "shouldIncludeAllFields": True,
    "semanticDimensions": [
        {
            "apiName": f"{base_table}_{dim['name']}",
            "label": dim["COMMENT"],           # Snowflake COMMENT → ラベル
            "dataType": sf_type(dim["DATA_TYPE"]),
            "dataObjectFieldName": f"{dim['name'].lower()}__c",
            "isVisible": True,
        }
        # ... Semantic View の DIMENSION ごとに自動生成
    ],
    "semanticMeasurements": [
        {
            "apiName": f"{base_table}_{fact['name']}",
            "label": fact["COMMENT"],
            "dataType": "Number",
            "dataObjectFieldName": f"{fact['name'].lower()}__c",
            "aggregationType": "Sum",
            "isAggregatable": True,
        }
        # ... Semantic View の FACT ごとに自動生成
    ],
})

4-3. メトリクスを各メジャーに対して作成

各メジャーに対応するメトリクスを作ります。時間ディメンション(DATE型)と追加ディメンション(VARCHAR型の最初のもの)を自動検出して紐付けます。SUSHIデータの場合、時間ディメンションには SALE_DATE、追加ディメンションには ITEM_NAME が自動的に選ばれます。

for fact in parsed["facts"]:
    sf_request("POST", f"{api}/{model_name}/metrics", token_info, {
        "apiName": f"{fact['name']}_mtc",
        "label": fact["COMMENT"],
        "description": fact["COMMENT"],
        "aggregationType": "Sum",
        "isCumulative": True,
        "timeGrains": ["Day", "Week", "Month", "Quarter", "Year"],
        "measurementReference": {
            "tableFieldReference": {
                "fieldApiName": f"{data_object_api}_{fact['name']}",
                "tableApiName": data_object_api,
            }
        },
        "timeDimensionReference": {        # DATE型ディメンション(SALE_DATE)を自動検出
            "tableFieldReference": {
                "fieldApiName": time_dim_api,
                "tableApiName": data_object_api,
            }
        },
        "additionalDimensions": [{          # VARCHAR型ディメンション(ITEM_NAME)を自動検出
            "tableFieldReference": {
                "fieldApiName": text_dim_api,
                "tableApiName": data_object_api,
            }
        }],
        "insightsSettings": {               # Tableau Semantics のInsights機能
            "sentiment": "SentimentTypeUpIsGood",
            "insightTypes": [
                {"enabled": True, "type": "TopContributors"},
                {"enabled": True, "type": "TrendChangeAlert"},
                {"enabled": True, "type": "CurrentTrend"},
                # ...
            ],
        },
    })

5. 同期対象の設定

Lambda環境変数 SYNC_TARGETS にJSON配列を書くだけで、複数テーブルを一括同期できます。

[
  {"semantic_view": "DB.SCHEMA.SV_SUSHI_SALES", "sf_workspace": "workspace"},
  {"semantic_view": "DB.SCHEMA.SV_SUSHI_INVENTORY", "sf_workspace": "workspace"}
]

モデル名は Semantic View 名から自動導出されます(SV_ を除去 + _SEMANTIC 付加)。

実行結果:

{
  "results": [
    {
      "model": "SUSHI_SEMANTIC_MODEL",
      "status": "ok",
      "stats": {"dims_synced": 4, "measures_synced": 2, "metrics_synced": 2, "workspace": "workspace"}
    }
  ]
}

6. ワークスペースへの割り当て

セマンティックモデルを作成しただけでは、Tableau Nextのワークスペースからは参照できません。Tableau Next REST APIを使って、ワークスペースにモデルを割り当てます。

model_info = sf_request("GET", f"{api}/{model_name}", token_info)
model_id = model_info["id"]

sf_request("POST", f"/services/data/v66.0/tableau/workspaces/{workspace}/assets", token_info, {
    "assetId": model_id,
    "assetType": "SemanticModel",
    "assetUsageType": "Referenced",
})

前提条件

この仕組みが動くには、Salesforce Data Cloud側のデータパイプラインが完成している必要があります

Data Stream → DLO → DMO のデータマッピングが完了していること。Snowflakeのテーブル名とDMO名が一致していること(SUSHI_SALESSUSHI_SALES__dlm)。Semantic Viewで定義した全カラムがDMO側にマッピング済みであること。

Tableau Nextで可視化する

同期されたセマンティックモデルをTableau Nextで確認すると、Snowflake側で定義したディメンション・メジャー・メトリクスがそのまま反映されています。


tableau-semantic

このセマンティックモデルを使ってダッシュボードを作成しました。


tableau-semantic-db

Tableau Cloudからの利用

同期したセマンティックモデルは、Tableau Nextだけでなく Tableau Cloud からも利用できます。

Tableau Cloudの「データに接続」画面にある「Tableau セマンティクス」コネクタから、SalesforceのインスタンスURL(https://your-org.my.salesforce.com)を入れてOAuthでサインインすると、Data Cloud上のセマンティックモデルにそのまま接続できます。Lambdaで同期したセマンティック情報も問題なくTableau Cloud側から参照できる状態になっていました。


tableau-cloud-semantic

Tableau Cloudでの可視化

Tableau Semanticsは特定のプロダクトに閉じた機能ではなく、Salesforceエコシステム全体のセマンティックレイヤーです。今回の同期の仕組みで1回セマンティックモデルを作れば、それが以下のサービスすべてから利用可能になります。

Tableau Next — Salesforce上の新世代BI

Tableau Cloud — 「Tableau セマンティクス」コネクタ経由で接続

CRM Analytics — Salesforceネイティブの分析ツール

Agentforce — AIエージェントがセマンティックモデルを参照して回答を生成

定義を1箇所に持って、複数の消費先に配るという考え方が、実際にそのまま動くのを確認できたのは嬉しい発見でした。

実装時の注意点

実装の過程でいくつかハマったポイントがあるので共有します。

sourceCreation の指定 — Authoring API でセマンティックモデルを作成する際、"sourceCreation": "DataCloud" を指定する必要があります。これを省略すると Other が設定され、Tableau Next の CLI(SFDX)からビジュアライゼーションをデプロイできなくなります。

Logical View を使わない — Authoring API には論理ビュー(Logical View)を作成するエンドポイントがありますが、これを使うとモデルの内部構造が UI 版と異なり、CLI からの viz デプロイが失敗します。Data Object をモデル直下に配置する構造にします。

ワークスペースへの割り当て — セマンティックモデルを作成しただけでは Tableau Next のワークスペースからは見えません。Tableau Next REST API(/services/data/v66.0/tableau/workspaces/{name}/assets)に POST してワークスペースに割り当てる必要があります。

フィールドのラベル — Snowflake Semantic View の COMMENT に日本語を書いておくと、Tableau Semantics 側のフィールドラベルに自動的に反映されます。COMMENT が空の場合はカラム名がそのままラベルになります。

考察

他のBIへの応用について

今回はTableau Semanticsを対象にしましたが、この「上流のセマンティック定義をAPIで渡す」というパターンは、セマンティックレイヤーAPIを持つ他のBIツールにも応用できると思います。

BIツール セマンティックAPI 応用方法
Tableau Semantics REST API (Authoring API) 本記事で実装済み
Looker LookML API LookML生成で対応可能
Power BI XMLA / REST API セマンティックモデルAPIあり
Lightdash YAML設定 YAML生成で対応可能

もちろん各ツールごとに型マッピングや命名規則の違いはありますが、「DESCRIBE SEMANTIC VIEW で構造を読み取って変換する」という根本のアプローチは同じです。Snowflake Semantic Viewを起点にしておけば、BIツールが変わっても上流の定義はそのまま使えるのではないかと思います。

まとめ

今回の取り組みでは、Snowflake Semantic Viewを上流の唯一の定義として、Tableau Semantics Authoring APIで同期する仕組みを作りました。DESCRIBE SEMANTIC VIEW → 型変換・命名規則変換 → REST API POST、という変換パイプラインで実現しています。

同期されたセマンティックモデルは、Tableau Nextだけでなく、Tableau Cloud・CRM Analytics・Agentforceからも利用可能なことを確認しました。セマンティックレイヤーAPIを持つBIツールであれば、同じアプローチが応用できるのではないかと考えています。

OSI標準化が進むまでの間、この「セマンティックゲートウェイ」は実用的な選択肢になると考えています。

なお、今回はAWS Lambda上で実装しましたが、変換ロジック自体はSnowflakeのストアドプロシージャやSnowpark上でも実現可能です。Snowflake内で完結させたい場合は、DESCRIBE SEMANTIC VIEW の結果をそのままプロシージャ内でパースし、Salesforce REST APIを呼ぶ構成にすることで、外部のコンピュート環境を用意せずに同期を回すこともできると思います。

参考

Snowflake公式ドキュメント: DESCRIBE SEMANTIC VIEW
Salesforce公式ドキュメント: Tableau Semantics Authoring API
Open Semantic Interchange (OSI) v1.0

アバター画像
大規模データエンジニア。 グループIT推進本部 全社データ技術局 データビジュアライゼーションチームに所属し、分析基盤の開発やAIエージェント関連の開発など、データ活用にまつわる開発を幅広く担当しています。