セマンティックモデル
VeloDB MCP Service(Apache Doris MCP Serverベース)により、AIエージェントはMCP protocolを通じて直接VeloDB Cloudのデータをクエリできます。2つのクエリパスを提供します:
- セマンティック層: 事前にYAMLでビジネスメトリクスを定義し、エージェントが自然言語でクエリを実行する際にシステムが正しいSQLを生成(推奨)。
- Raw SQL: メトリクスが一致しない場合の読み取り専用SQLクエリへのフォールバック。
このページではセマンティックモデルの作成と管理について説明します。エンドユーザーとしての接続とクエリについては、User Guideをご覧ください。
セマンティックモデルとは?
セマンティックモデルは、データベーステーブルのビジネス記述です。システムに以下を指示します:
-
テーブルの主キー(エンティティ)
-
グループ化に使用できるフィールド(ディメンション)
-
集計が必要なフィールド(メジャー)
一度定義されると、ユーザーは自然言語レベルのクエリ(「月別の合計注文金額を表示して」)を実行でき、システムが自動的に正しいSQLを生成します。
YAMLが仕様でMetricFlowが翻訳機:「月別の合計注文金額」をSELECT DATE_TRUNC('month', order_date), SUM(amount) FROM orders GROUP BY 1に変換します。
クイックスタート
ステップ1: YAMLファイルを作成
各YAMLファイルは1つのテーブルを記述します。models/ディレクトリ下に配置します:
# models/orders.yaml
---
semantic_model:
name: orders # model name
db_table: dw.orders # the corresponding VeloDB table
defaults:
agg_time_dimension: order_date # default time dimension
entities:
- name: order_id # primary key
type: primary
expr: order_id
dimensions:
- name: order_date # time dimension
type: time
type_params:
time_granularity: day
- name: channel # categorical dimension
type: categorical
measures:
- name: total_amount # total order amount
agg: sum
expr: amount
- name: order_count # order count
agg: count
expr: order_id
ステップ2: 時間設定の定義
期間対期間および前年同期比の時間メトリクスで使用されるカレンダーテーブルを指定するproject.yamlが必要です:
# models/project.yaml
---
time_config:
calendar:
- table: dw.dim_date
column: date_id
grain: day
ステップ 3: 検証とコミット
-
Validate をクリックして、モデルが正しいことを確認する
-
検証に合格したら、Commit をクリックしてモデルを有効にする
-
list_metricsを使用して利用可能なメトリクスを表示し、query_metricを使用してデータを照会する
テーブルが存在するか、列名が正しいか、エンティティとディメンションが完全であるかどうか。何か問題がある場合は、具体的なエラーとその場所を返します。
セマンティックモデル構造
完全な semantic_model には以下のフィールドが含まれます:
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
name | string | ✅ | グローバルに一意なモデル名。小文字で開始し、数字とアンダースコアを含むことができます |
db_table | string | ✅ | VeloDB 物理テーブル、database.table 形式、例:dw.orders |
defaults | object | ✅ | デフォルト設定。現在は agg_time_dimension を含む必要があります |
entities | list | ✅ | テーブルのエンティティ定義。少なくとも1つの type: primary メインエンティティ |
dimensions | list | ✅ | グループ化とフィルタリング用のディメンション |
measures | list | 推奨 | 集約定義。定義すると、自動的に照会可能なメトリクスになります |
description | string | オプション | モデルのテキスト説明 |
label | string | オプション | 表示名 |
primary_entity | string | 条件付き | entities に type: primary エンティティがない場合に必須 |
すべての名前(モデル、エンティティ、ディメンション、メジャー)は以下の条件を満たす必要があります:
-
小文字で開始する
-
小文字、数字、アンダースコアのみを含む
-
連続する2つのアンダースコア
__を含まない -
少なくとも2文字である
✅ order_id, total_amount, user_count
❌ OrderID, order__id, a
エンティティ — テーブルの識別情報
エンティティは行の一意性と関係性を定義します。すべてのテーブルには1つのメインエンティティが必要です。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
name | string | ✅ | エンティティ名、このモデル内で一意 |
type | enum | ✅ | エンティティ型(下表を参照) |
expr | string | 推奨 | 対応するデータベース列。省略可能(デフォルトは name);SQL式もサポート |
description | string | オプション | テキスト説明 |
label | string | オプション | 表示名 |
エンティティ型
| 型 | 意味 | 使用する場面 |
|---|---|---|
primary | 主キー。行ごとに一意、すべてのレコードをカバー | テーブルのID列。各テーブルには正確に1つの primary エンティティが必要 |
foreign | 外部キー。重複やnullを含む可能性あり | 他のテーブルに結合する列、例:customer_id や product_id |
unique | 一意キー。行ごとに一意、すべてのレコードをカバーしない可能性あり | 例:メールアドレスやID番号 |
natural | 自然キー。実世界の一意識別子 | 例:商品バーコードや従業員番号 |
例:orders テーブルのエンティティ定義
entities:
- name: order_id # primary key: the unique ID of each order
type: primary
expr: order_id
- name: customer # foreign key: joins to the users table
type: foreign
expr: user_id
- name: order_ref # foreign key + SQL expression
type: foreign
expr: substring(trace_id FROM 1 FOR 8)
テーブルにtype: primaryエンティティがない場合は、モデルのトップレベルでprimary_entity: entity_nameを使用してください。
Dimensions — データのグループ化方法
Dimensionsはデータのグループ化とフィルタリング方法を定義します。time dimensionsとcategorical dimensionsの2つのタイプがあります。
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Dimension名 |
type | enum | ✅ | timeまたはcategorical |
type_params | object | timeの場合必須 | 時間粒度の設定(下記参照) |
expr | string | 推奨 | 対応するカラムまたはSQL式 |
is_partition | bool | オプション | パーティションカラムかどうか。デフォルトはfalse |
description | string | オプション | テキストによる説明 |
label | string | オプション | 表示名 |
Time Granularity(time_granularity)
| Granularity | 意味 | 例 |
|---|---|---|
day | 日別 | 2025-01-15 |
week | 週別 | 2025-W03 |
month | 月別 | 2025-01 |
quarter | 四半期別 | 2025-Q1 |
year | 年別 | 2025 |
hour | 時別 | 2025-01-15 14:00 |
minute | 分別 | 2025-01-15 14:30 |
例
dimensions:
- name: order_date # order date (by day)
type: time
type_params:
time_granularity: day
expr: order_date
- name: order_month # order month (by month)
type: time
type_params:
time_granularity: month
expr: order_date # same column, different granularity
- name: channel # channel (categorical)
type: categorical
expr: channel
- name: status_label # with a SQL expression
type: categorical
expr: concat(status, '_', channel)
Measures — 集約
Measuresはデータ列に対する集約を定義します。各measureは自動的に同じ名前のクエリ可能なmetricを生成します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
name | string | ✅ | Measure名(metric名にもなります) |
agg | enum | ✅ | 集約タイプ(下記のテーブルを参照) |
expr | string | 推奨 | 集約する列またはSQL式 |
description | string | オプション | Metricの説明 |
label | string | オプション | 表示名 |
create_metric | bool | オプション | falseに設定するとmetricを自動生成しません。デフォルトはtrue |
agg_time_dimension | string | オプション | モデルのデフォルト時間次元を上書きします |
集約タイプ
| タイプ | 意味 | 典型的な用途 |
|---|---|---|
sum | 合計 | 合計金額、合計数 |
count | カウント | 注文数、ユーザー数 |
count_distinct | 重複なしカウント | ユニークユーザー、アクティブデバイス |
average | 平均 | 平均金額、平均時間 |
min | 最小値 | 最低価格、最早時間 |
max | 最大値 | 最高価格、最遅時間 |
median | 中央値 | 注文金額の中央値 |
percentile | パーセンタイル | P99レイテンシ、P95金額(agg_params.percentileが必要) |
sum_boolean | Boolean合計 | コンバージョン数、合格数 |
例
measures:
- name: total_amount # total order amount
description: "Sum of all order amounts"
agg: sum
expr: amount
label: "Total Amount"
- name: order_count # order count
agg: count
expr: order_id
- name: unique_customers # distinct customers
description: "Number of distinct customers who placed an order"
agg: count_distinct
expr: user_id
- name: p99_amount # P99 order amount
agg: percentile
expr: amount
agg_params:
percentile: 0.99
- name: internal_counter # not exposed as a metric
agg: sum
expr: raw_value
create_metric: false
完全な例
以下は、eコマースシナリオ(orders table)の完全なsemantic-modelの定義です:
# models/orders.yaml — orders fact table
---
semantic_model:
name: orders
description: "E-commerce order fact table; each row is one order"
db_table: dw.orders
defaults:
agg_time_dimension: order_date
# ── Entities ──
entities:
- name: order_id
description: "Order primary key"
type: primary
expr: order_id
- name: customer
description: "Associated user"
type: foreign
expr: user_id
- name: product
description: "Associated product"
type: foreign
expr: product_id
# ── Dimensions ──
dimensions:
- name: order_date
description: "Order date (by day)"
type: time
type_params:
time_granularity: day
expr: order_date
- name: order_month
description: "Order month"
type: time
type_params:
time_granularity: month
expr: order_date
- name: channel
description: "Order channel"
type: categorical
expr: channel
- name: status
description: "Order status"
type: categorical
expr: status
# ── Measures ──
measures:
- name: total_amount
description: "Total order amount"
label: "Total Amount"
agg: sum
expr: amount
- name: order_count
description: "Total order count"
label: "Order Count"
agg: count
expr: order_id
- name: unique_customers
description: "Distinct customers who placed an order"
label: "Distinct Customers"
agg: count_distinct
expr: user_id
- name: avg_amount
description: "Average order amount"
label: "Average Order Value"
agg: average
expr: amount
Companion: usersテーブルとproductsテーブル
# models/users.yaml — users dimension table
---
semantic_model:
name: users
description: "User dimension table"
db_table: dw.users
defaults:
agg_time_dimension: register_date
entities:
- name: user_id
type: primary
expr: user_id
dimensions:
- name: register_date
type: time
type_params:
time_granularity: day
- name: city
type: categorical
- name: level
type: categorical
measures:
- name: user_count
agg: count
expr: user_id
# models/products.yaml — products dimension table (pure dimension table, no measures, so defaults is omitted)
---
semantic_model:
name: products
description: "Product dimension table"
db_table: dw.products
entities:
- name: product
type: primary
expr: product_id
dimensions:
- name: product_name
type: categorical
expr: name
- name: category
type: categorical
expr: category
- name: brand
type: categorical
expr: brand
高度なメトリック定義
measuresから自動生成される単純なメトリックに加えて、metric:ドキュメントを使用して高度なメトリックを定義できます。高度なメトリックは、既存のmeasuresやmetricsを組み合わせて、より複雑なロジックを実装します。4つのタイプがサポートされています:
| タイプ | 意味 | 典型的なシナリオ |
|---|---|---|
ratio | 比率メトリック:分子 ÷ 分母 | コンバージョン率、利益率、シェア |
derived | 派生メトリック:既存のメトリックに対する式 | 前期比成長、前年同期比変化、加重計算 |
cumulative | 累積メトリック:時間枠での累積 | 過去7日間の売上、月次累積登録数 |
conversion | コンバージョンメトリック:2つのイベント間のコンバージョン分析 | 注文コンバージョン率、登録コンバージョン率 |
Ratioメトリック
2つのメトリックの比率を計算します。例:ユーザーあたり注文数 = 注文数 / ユーザー数。
# models/orders_per_user.yaml
---
metric:
name: orders_per_user
description: "Orders per user: order count / user count"
type: ratio
type_params:
numerator: order_count # numerator: references an existing metric
denominator: user_count # denominator: references an existing metric
分子と分母の両方は、既に定義されたメトリック名である必要があります(シンプルメトリックまたは他のアドバンストメトリックのいずれか)。
Derived Metrics
式を使用して1つ以上の既存のメトリックから計算されます。前期比や前年比の計算で最もよく使用されます。
# models/revenue_growth.yaml — period-over-period growth
---
metric:
name: revenue_growth
description: "Revenue period-over-period growth rate"
type: derived
type_params:
expr: (current_revenue - prev_revenue) / prev_revenue
metrics:
- name: total_amount # current-period revenue
alias: current_revenue
- name: total_amount # prior-period revenue (same metric, with an offset)
alias: prev_revenue
offset_window: 1 month # shift back by one time window
| Parameter | Description |
|---|---|
expr | 計算式;各入力メトリックをaliasで参照する |
metrics | 入力メトリックのリスト |
name | 参照されるメトリック名 |
alias | exprで使用されるエイリアス |
offset_window | 時間オフセット、例:1 month、7 days、1 year |
offset_to_grain | オフセット先の粒度、例:month、year |
累積メトリック
時間窓内でメトリックを蓄積する、例:「過去7日間の売上」。
# models/weekly_sales.yaml
---
metric:
name: weekly_sales
description: "Sales over the last 7 days"
type: cumulative
type_params:
measure:
name: total_amount
window: 7 days # time window: the past 7 days
| パラメータ | 説明 |
|---|---|
measure | 参照される measure 名(semantic_model の measures から) |
window | 時間窓の形式 number granularity、例:28 days、4 weeks、3 months |
grain_to_date | オプション。指定された粒度まで累積する、例:month(月初来)、year(年初来) |
Conversion Metrics
ユーザーがあるイベント(ベース)から別のイベント(コンバージョン)に変換する率を測定します。ユーザーファネルの分析によく使用されます。
# models/order_conversion.yaml
---
metric:
name: register_to_order_conversion
description: "Registration-to-order conversion rate"
type: conversion
type_params:
conversion_type_params:
base_measure: # base event (registration)
name: user_count
conversion_measure: # conversion event (order)
name: order_count
entity: user # join entity: the dimension to compute conversion by
calculation: conversion_rate # calculation method
| パラメータ | 説明 |
|---|---|
base_measure | ベースイベントのメジャー名 |
conversion_measure | コンバージョンイベントのメジャー名 |
entity | コンバージョンを計算するための結合エンティティ(通常はユーザーまたはセッション) |
calculation | conversion_rate(率)またはconversions(絶対数) |
window | オプション。コンバージョンウィンドウ、例:7 days |
一般的なシナリオ
シナリオ1:異なる粒度でのディメンションとしての同じカラム
単一の日付カラムで、日、週、月のディメンションを一度に定義できます:
dimensions:
- name: order_date
type: time
type_params:
time_granularity: day
expr: order_date
- name: order_week
type: time
type_params:
time_granularity: week
expr: order_date # same column!
- name: order_month
type: time
type_params:
time_granularity: month
expr: order_date # same column!
シナリオ2: SQL式の使用
列名が直感的でない場合や計算フィールドが必要な場合は、SQL式を使用します:
dimensions:
- name: user_label
type: categorical
expr: concat(level, '_', city) # concatenated field
entities:
- name: user_short_id
type: foreign
expr: substring(trace_id FROM 1 FOR 8) # substring
measures:
- name: net_amount
agg: sum
expr: coalesce(amount, 0) - coalesce(discount, 0) # computed field
substring、concat、coalesce、castなどの標準SQL関数。これらの式は物理検証時に認識され、列名チェックをスキップします。
シナリオ3: パーティション化されたテーブル
テーブルにパーティション列がある場合は、is_partition: trueでマークします:
dimensions:
- name: ds
type: time
type_params:
time_granularity: day
is_partition: true # mark as the partition column
expr: ds
シナリオ 4: 内部measureの非表示
一部のmeasureは中間計算のみに使用され、エンドユーザーに公開すべきではありません。create_metric: falseを設定してください:
measures:
- name: total_amount # ✅ public metric
agg: sum
expr: amount
- name: _raw_count # ❌ not exposed
agg: count
expr: order_id
create_metric: false
高度な機能
フィルター
measure定義またはmetric定義にSQLフィルター条件を追加できます。フィルターは集計前に適用されます。
-
measuresエントリのfilter:フィールド — 単一のmeasureのデータ範囲を制限します -
metric:のfilter:フィールド — metric全体のデータ範囲を制限します -
measureのinput_measures[].filter:— 高度なmetricによって参照されるmeasureを制限します
# Example 1: measure-level filter — only the total amount of "completed" orders
measures:
- name: completed_amount
description: "Sum of completed order amounts"
agg: sum
expr: amount
filter: {{ render_dimension_template('status') }} = 'completed'
# Example 2: metric-level filter
---
metric:
name: premium_user_orders
description: "Order count for premium users"
type: simple
type_params:
measure:
name: order_count
filter: {{ render_dimension_template('user_level') }} = 'premium'
-
YAMLでは、
{{ Dimension('qualified_name') }}または{{ render_dimension_template('dimension_name') }}でdimensionを参照します -
{{ Entity('entity_name') }}または{{ render_entity_template('entity_name') }}でentityを参照します -
通常のSQL条件を続けて記述します(例:
= 'value'、IN ('a', 'b')) -
query_metricのwhereパラメータは生のSQLを直接受け取ります(例:"channel = 'APP'")。コンパイラが自動的にMetricFlowテンプレート構文に変換します
Saved Queries
metrics + grouping + filtersの頻繁に使用される組み合わせを、ユーザーが直接呼び出せるクエリテンプレートとして保存します。
# models/weekly_report.yaml
---
saved_query:
name: weekly_revenue_report
description: "Weekly revenue report: total order amount and order count grouped by channel"
label: "Weekly Revenue Report"
query_params:
metrics:
- total_amount
- order_count
group_by:
- order_id__order_week # group by week
- order_id__channel # group by channel
order_by:
- "-order_id__order_week" # descending by week
limit: 52
| フィールド | 説明 |
|---|---|
metrics | クエリするメトリック名のリスト |
group_by | グループ化ディメンション、entity_name__dimension_name形式(二重アンダースコアで結合) |
order_by | ソート;-プレフィックスは降順を意味する |
where | フィルター条件(filtersと同じ構文) |
limit | 最大行数 |
entity_name__dimension_name(二重アンダースコア)。例:order_id__order_dateはordersテーブルのorder_dateディメンションです。
Non-additive Measures & Slowly Changing Dimensions (SCD Type II)
一部のメジャーは単純に合計することができず(在庫や口座残高など)、特定のディメンションに沿ったスナップショット値が必要です。
# Non-additive measure: inventory (month-end snapshot)
measures:
- name: monthly_inventory
description: "Month-end inventory"
agg: sum
expr: inventory_count
non_additive_dimension:
name: snapshot_date # the non-additive dimension
window_choice: max # take the maximum within the time window
window_groupings:
- product # snapshot grouped by product
SCD Type II (slowly changing dimensions): ディメンションテーブルに有効期間がある場合、開始と終了のディメンションをマークします:
# Mark SCD Type II in the dimension table
dimensions:
- name: valid_from
description: "Validity start time"
type: time
type_params:
time_granularity: day
validity_params:
is_start: true # mark as the start time
- name: valid_to
description: "Validity end time"
type: time
type_params:
time_granularity: day
validity_params:
is_end: true # mark as the end time
Null埋めとタイムライン整列
# Replace NULL with 0 (useful so count-type metrics show 0 on dates with no data)
metric:
name: daily_orders
type: simple
type_params:
measure:
name: order_count
fill_nulls_with: 0 # show 0 on dates with no data
join_to_timespine: true # align to the timeline (fill in missing dates)
| Parameter | Description |
|---|---|
fill_nulls_with | 集約結果のNULLを指定された値(通常は0)で置き換える |
join_to_timespine | メトリック結果をタイムラインテーブルと結合して、すべての日/月/年に行が存在するようにする(欠落した日付はNULLまたは0で埋められる) |
Native Table Reference Format
db_tableの短縮形に加えて、MetricFlowのネイティブnode_relationフォーマットもサポートされており、3部構成のカタログ参照も含まれます:
# Two-part: database.table
node_relation:
schema_name: dw
alias: orders
# Three-part: catalog.database.table
node_relation:
database: catalog
schema_name: dw
alias: orders
# db_table also supports the three-part form
db_table: catalog.dw.orders
Cumulative Metricsの集約モード
Cumulative metricsは、時間窓内での集約を制御する3つのperiod_aggモードをサポートします:
# last: take the value of the last day in the window (default behavior)
metric:
name: end_of_week_inventory
type: cumulative
type_params:
cumulative_type_params:
measure:
name: inventory_count
window: 7 days
period_agg: last # take the last day's value
# average: daily average within the window
period_agg: average # 7-day average
# first: the value of the first day in the window
period_agg: first # take the first day's value
period_agg | 説明 |
|---|---|
last | ウィンドウ内の最終日の値(デフォルト) |
average | ウィンドウ内の日次平均 |
first | ウィンドウ内の初日の値 |
コンバージョンメトリクスの定数プロパティ
コンバージョンメトリクスでは、constant_propertiesを使用して、2つのイベント間で一定に保たれる必要があるプロパティを指定します:
# Analyze conversion by "traffic source", requiring the source to be the same across both events
metric:
name: register_to_order_by_source
type: conversion
type_params:
conversion_type_params:
base_measure:
name: user_count
conversion_measure:
name: order_count
entity: user
constant_properties:
- base_property: order_id__channel # the base event's property
conversion_property: order_id__channel # the conversion event's property (must match)
Metric Time Granularity & Offset Grain
Metric レベルの time_granularity: metric 定義内で直接時間粒度を設定できます(クエリ時のデフォルトを上書きします):
metric:
name: monthly_revenue
type: simple
time_granularity: month # this metric defaults to monthly aggregation
type_params:
measure:
name: total_amount
offset_to_grain: 派生メトリクスにおいて、オフセットを指定されたgrainに合わせます(デフォルトの日レベルではなく):
metric:
name: yoy_growth
type: derived
type_params:
expr: (current - prev) / prev
metrics:
- name: total_amount
alias: current
- name: total_amount
alias: prev
offset_window: 1 year
offset_to_grain: month # offset to month grain (rather than day)
エンティティロール
同一のエンティティ(user_idなど)は、テーブル内で複数の役割を担う場合があります。例えば、ordersテーブルのuser_idは「購入者」と「紹介者」の両方の役割を持ちます。これらを区別するためにroleを使用します:
entities:
- name: user
type: foreign
expr: buyer_id
role: buyer # this user entity's role is "buyer"
- name: user
type: foreign
expr: referrer_id
role: referrer # this user entity's role is "referrer"
roleが指定されていない場合、デフォルトのroleはエンティティ名と同じになります。
ベストプラクティス
-
テーブルごとに1つのファイル。 明確で保守しやすい構造にするため、ファイル名は
table_name.yamlとします。✅
orders.yaml,users.yaml,products.yaml -
エンティティを最初に定義し、次にdimension、そしてmeasureを定義する。 エンティティはセマンティックモデルの骨格であり、dimensionはグループ化を提供し、measureはクエリのターゲットです。この順序で記述することで、漏れを防ぐことができます。
-
すべてのmeasureに
descriptionを記述する。 エンドユーザーはメトリック名とdescriptionを見ます。適切なdescriptionにより、YAMLを読まなくてもメトリックを理解できます。 -
同じ時間カラムで複数の粒度のdimensionを定義できる。 たとえば、
order_dateカラムでは、day、week、month、quarter、yearの粒度を同時に持つことができます。 -
外部キーエンティティには意味のあるビジネス名を使用する。 エンティティ名
customerはuser_idよりも理解しやすく、「user_idカラム」ではなく「顧客」の概念を表します。 -
コミット前に検証する。 YAMLを変更するたびに、Validateをクリックします。システムはテーブルの存在、カラム名の正確性、命名規則をチェックします。パスした後にのみコミットします。
-
measure名はモデル内で一意でなければならない。 measure名はモデル間で重複できますが、それはメトリックオーバーライドを引き起こすため、グローバルに一意に保つのがベストです。
よくあるエラーと対処法
| エラーメッセージ | 原因 | 修正方法 |
|---|---|---|
Table xxx does not exist | db_tableが指すテーブルが存在しない | テーブル名のスペルを確認し、データベース名とテーブル名の両方が正しいことを確認する |
measure references missing column: dw.orders.xxx | measureが参照するカラムがテーブルに存在しない | exprが実際のカラム名と一致することを確認する(大文字小文字に注意) |
entity references missing column | エンティティのexprが参照するカラムが存在しない | 上記と同様。SQL式(例:substring(...))の場合は、関数名とカラム名を確認する |
Duplicate measure 'xxx' defined in 2 models | 2つのモデルで同じ名前のmeasureが定義されている | measureの1つを名前変更してグローバルに一意にする |
Duplicate semantic_model name | 2つのファイルで同じモデル名が使用されている | モデルの1つを名前変更する |
Did not find exactly one project configuration | project.yamlが見つからない | time_configを含むproject.yamlを作成する |
'xxx' does not match '^(?!.*__)...$' | 名前が命名規則に違反している | 小文字で始め、二重アンダースコアを削除し、2文字以上にする |
No staging changes to validate | 検証する変更がない | 最初にYAMLファイルをアップロードまたは編集してから、Validateをクリックする |
-
VeloDBでテーブルが存在することを確認:
DESCRIBE dw.orders -
大文字小文字を含めてカラム名が完全に一致することを確認
-
YAMLのインデントが正しいことを確認(タブではなくスペースを使用)
-
すべての名前が小文字始まりの規則に従っていることを確認
VeloDB MCP Serviceでのセマンティックモデル管理
Workspace
workspaceはセマンティックモデルの分離されたコンテナです。各workspaceは以下を持ちます:
-
モデルファイル(YAML定義)
-
メトリックリスト(
list_metricsはこのworkspaceのメトリックのみを表示) -
クエリエンジンインスタンス(MetricFlowコンパイラ)
-
VeloDB接続プール
Workspace Aのメトリックはworkspace Bから完全に見えません。これはチーム、プロジェクト、環境ごとの分離に適しています。
workspace名は文字で始まり、文字、数字、アンダースコアのみを含む必要があります。例:marketingまたはfinance_v2。
3つのWorkspace状態
check_service_healthを呼び出すと、各workspaceの実行時状態が表示されます。workspaceは常に3つの状態のいずれかにあります:
| 状態 | アイコン | 意味 | トリガー |
|---|---|---|---|
| healthy | 🟢 | 正常に動作中。セマンティックモデルが正常にロードされ、メトリックがクエリ可能。 | YAMLファイルがコミットされ、ブートストラップ解析が成功し、MetricFlowエンジンが準備完了。 |
| no_models | ⚪ | 空のworkspace。まだYAMLファイルがアップロードされていない。 | 新しく作成されたworkspace、またはすべてのファイルが削除された。 |
| not_ready | 🔴 | ロード失敗。ファイルは存在するがセマンティックマニフェストにコンパイルできない。 | YAML構文エラー、テーブル不在、project.yaml不在、MetricFlow検証失敗など。validateのエラーメッセージを確認。 |
┌──────────────┐ upload YAML ┌──────────────┐ commit OK ┌──────────────┐
│ no_models │ ──────────────→ │ not_ready │ ───────────────→ │ healthy │
│ (empty) │ │ (to fix) │ │ (running) │
└──────────────┘ └──────────────┘ └──────────────┘
↑ │
│ upload a bad YAML │
└──────────────────────────────────┘
各リロード後、システムはバージョン番号、メトリック数、および読み込みが成功したかどうかを記録します。現在読み込まれているメトリック数を確認するには、check_service_healthによって返されるmetric_countを使用してください。
二層ストレージ:Active StoreとStaging Store
各ワークスペースは内部的に2つのストレージ層を持ちます:
| ストレージ層 | テーブル | 目的 |
|---|---|---|
| Active Store(ライブ) | active_store_{workspace} | コミット済みおよび読み込み済みモデル。クエリエンジンはこのバージョンを使用します。ファイルは読み取り専用です。 |
| Staging Store(保留中) | staging_store_{workspace} | ユーザーによってアップロードまたは編集された保留中の変更。追加/変更/削除が許可されています。検証に合格後、Activeに昇格されます。 |
Staging Store Active Store
┌─────────────┐ commit ┌─────────────┐
│ edit / add │ ─────────→ │ query use │
│ validate ✓ │ │ read-only │
│ discard ✗ │ │ │
└─────────────┘ └─────────────┘
↑ ↑
user edits query engine
更新フロー
セマンティックモデルの更新は、編集 → 検証 → コミット → 自動リロードのフローに従います:
| ステップ | アクション | 説明 |
|---|---|---|
| 1 | YAMLのアップロード/編集 | ファイルがStaging Store に入ります(実行中のクエリには影響しません) |
| 2 | Validate | 必須!システムがテーブルの存在、カラムの正確性、YAML構文、MetricFlowセマンティックルール、命名ルール、および モデル間の重複名をチェックします |
| 3 | Commit | Staging → Active。システムが自動的にエンジンリロードをトリガーします(手動再起動は不要) |
| 4 | ⟳ 自動リロード | バックグラウンドスレッドが新しいモデルを解析し、JSONマニフェストをコンパイルし、ツールルーティングを更新します。通常2-5秒で完了します |
ValidateをパスしていないStagingはCommit時に拒否され、"Staging must be validated before commit"が返されます。
権限モデル
セマンティックモデルの管理はadminユーザーのみ可能です:
| アクション | admin | 一般ユーザー |
|---|---|---|
| セマンティックモデルの表示 | ✅ | ✅ |
メトリックのクエリ(query_metric) | ✅ | ✅ |
メトリックのリスト(list_metrics) | ✅ | ✅ |
| YAMLのアップロード/編集/削除 | ✅ | ❌ |
| Validate / Commit / Discard | ✅ | ❌ |
| ワークスペースの作成/削除 | ✅ | ❌ |
SQLの実行(execute_query) | ✅ | ✅(制限あり) |
デフォルトのExampleワークスペース
初回起動時、システムは完全なシードデータを持つexampleワークスペースを自動的に作成します:
| コンテンツ | 説明 |
|---|---|
dw.orders | 注文テーブル(12行のモックデータ):order_id, user_id, product_id, amount, channel, status, order_date |
dw.users | ユーザーテーブル(5行のモックデータ):user_id, name, city, level, register_date |
dw.products | 商品テーブル(5行のモックデータ):product_id, name, category, brand, price |
dw.dim_date | 日付ディメンション(カレンダー)テーブル、タイムライン調整と累積計算に使用 |
| Semantic-model YAML | orders.yaml, users.yaml, products.yaml + project.yaml(active_store_exampleに自動注入) |
サンプルメトリックには、ordersモデルからtotal_amount(総注文金額)、order_count(注文数)、avg_amount(平均注文値)、unique_users(ユニークユーザー)、およびusersモデルからuser_count(ユーザー数)が含まれます。
自動シードを無効にするには、設定でseed_example: falseを設定してください。
WebUI管理インターフェース
WebUI(ブラウザインターフェース)
http://<server-address>:<port>/mcp/webにアクセスしてサインインし、グラフィカル管理インターフェースを使用してください:
| ページ | URL | 機能 |
|---|---|---|
| サインイン | /mcp/web/login | VeloDBアカウントでサインイン(admin:adminがデフォルト管理者) |
| ホーム | /mcp/web | ワークスペースリスト;ワークスペースの切り替え、作成、削除 |
| モデル管理 | /mcp/web/models?workspace=xxx | ActiveとStagingのファイルリストを表示;編集、アップロード、削除 |
| ファイルエディター | /mcp/web/{filename}?workspace=xxx | シンタックスハイライト付きでYAMLファイルをオンライン編集 |
主要アクションボタン(admin のみ):
| ボタン | アクション |
|---|---|
| Validate | すべてのStagingの変更を検証(物理 + セマンティック検証 + 重複検出) |
| Commit | 検証済みStagingをActiveに昇格し、エンジンリロードをトリガー |
| Discard | すべてのStagingの変更を破棄し、Activeバージョンに戻す |
| Reload | 手動でエンジンリロードをトリガー(通常はCommit後に自動) |
| + New | 新しいYAMLファイルを作成 |
次のステップ
- User Guide — VeloDB MCP ServiceをAIエージェントに接続し、自然言語でデータをクエリします。