面向读者:数据平台/数仓/湖仓架构师、数据工程师、分析工程师、AI 应用工程师、数据治理负责人
- 背景:为什么“语义”成了 AI 时代的数据平台刚需 传统 BI 时代,数据团队最常见的内耗之一就是:同一个指标,不同团队算出不同结果。
到了 GenAI / Agentic Analytics 这波浪潮,这个坑不但没消失,反而更容易被放大:
业务同学问一句“本季度 NRR 多少?”
BI 报表给出一个数字
数据科学同学在 Notebook 里算出另一个
LLM 做 Text-to-SQL 又吐出第三个数字,还能顺便写一段听起来很“像那么回事”的解释
很多时候锅不在工具,而在更基础的东西:
业务概念没有以结构化方式沉淀成可复用资产
语义没有变成平台级资产(平台原生、可治理、可发布)
说得直白一点:组织需要一层稳定的“翻译器”,把业务语言和数据的物理结构(表、字段、Join 、过滤、权限)对齐起来,并且让 BI、数据应用、AI/Agent 都复用同一套定义。
本文要聊的核心就是:Semantic View。
- Semantic View 是什么?不是普通 View,也不只是“指标层” 2.1 定义(从平台视角看) 你可以把 Semantic View 理解为:
Semantic View(语义视图),本质上是在数据之上加一层“可理解的业务语义层”,把底层复杂的数据结构(表、字段、Join、计算逻辑)抽象成业务可读、可复用的指标与维度。
一个像样的 Semantic View,通常至少要解决这些事:
抽象:把物理表结构抽象成业务对象(指标、维度、实体关系)
一致:指标定义一次,多工具复用,少写一堆重复 SQL
可治理:权限、审计、血缘、认证等跟着语义对象走
AI 就绪:给机器一份“读得懂、查得到”的业务上下文,别让模型靠猜
2.2 和普通 SQL View / Dataset 的差别 维度 普通 SQL View 语义 View(Semantic View) 目标 复用查询 / 简化 SQL 统一业务语义 + 多消费面输出一致 指标可重用性 指标常写死在 select / group by 指标定义与维度分组解耦,运行时按任意维度切片 Join 管理 依赖使用者手写 关系声明是模型的一部分,可复用/可推导 治理 主要靠底层表/视图权限 语义对象可携带治理与元数据(owner、certification、policy、audit) AI 友好性 LLM 仍要理解字段含义/Join 路径 提供“业务词典 + 指标定义 + 同义词 + guardrails” 2.3 语义层、指标层、语义 View:怎么把这些名词放回正确位置 行业里叫法很多:Semantic Layer、Metrics Layer、Semantic Model、Metric View、Semantic View……
如果用更工程化一点的拆法,会清楚不少:
语义层(Semantic Layer):一组能力的集合,用来统一业务语义
语义模型(Semantic Model):语义层里的模型定义(实体/关系/维度/指标/规则)
语义视图(Semantic View):语义模型在平台里的可执行/可发布形态(对象/资源/接口)
指标层(Metrics Layer):语义层的一个子集,更聚焦指标的标准化与复用
落地时常见几种形态:
把 Semantic View 做成数据库内对象(schema-level object)
做成 catalog 管理的对象,用 YAML/DSL 描述
或者干脆做成 headless API(语义层服务化)
- 为什么在 AI + 数据平台里,Semantic View 更重要? 3.1 让 AI 从“写 SQL”变成“调用业务真相接口” 纯 Text-to-SQL 的坑其实挺集中:
字段含义不确定:revenue、sales_amount、gmv 到底哪个是财务口径?
Join 路径不确定:订单 join 用户,还是账单 join 合同?
过滤条件容易漏:测试账号、退款、内部订单、跨期规则……
难审计:LLM 生成的 SQL 怎么保证口径一致、怎么追责?
Semantic View 的思路更像“先把规则固化,再让调用方组合”。常见链路大概是:
复杂逻辑提前沉淀成指标/维度/关系
查询时尽量少直接碰底层明细表
先检索语义模型(可用指标、维度、释义、同义词、权限)
再通过平台提供的语义查询接口执行
结果很直观:AI 的工作从“生成任意 SQL”变成“选对语义对象并组合查询”。模型能发挥的空间变小了,稳定性反而更高。
3.2 让组织从“对数”走向“对语义资产” 没有语义层时,很多团队的协作路径是这样的:
会上对齐一次口径
然后把口径塞进各类报表、脚本、Notebook
口径一变,开始到处改、到处对数
有了语义层/语义视图后,协作对象就更像“资产”:
可版本化的语义定义(Semantics as Code)
可认证、可审计的指标资产
从治理角度看,这类投入减少的是“决策债务”:口径越晚统一,未来返工和扯皮的成本越高。
3.3 让治理更像系统能力,而不是每个工具重复配置 多 BI、多数据应用、多 Agent 的环境里,差异会很明显:
语义散落在各工具:权限、行列级策略、脱敏、审计要重复做
语义对象在平台内:治理策略跟着语义对象走,消费面天然继承
这在合规场景(审计、访问记录、可追溯性)里尤其关键。
- Semantic View 的核心能力清单(你通常会期待它具备什么) 下面按“能力清单”把一个成熟的 Semantic View(或语义层)常见要素梳理一下。
4.1 语义建模:指标、维度、实体关系 维度(Dimensions):切片、分组、过滤的业务属性
例:地区、渠道、客户等级、产品层级、财年、自然月
度量/指标(Measures / Metrics):可聚合的业务结果
例:收入、活跃用户数、NRR、转化率、留存率
关系(Relationships):实体之间如何连接
例:订单→用户、账单→合同、商品→类目
关键点:指标定义要和维度分组解耦。否则它很快就退化成“固定粒度 view”,下游还是会在不同场景里算出不一致的结果。
示例:用 YAML / DDL 定义“非累加指标”(Non-additive / Semi-additive) 语义层最“值钱”的内容之一,就是非累加指标。原因很简单:这类指标在不同粒度下二次聚合很容易错。
常见例子:
distinct_customer_count:去重客户数(聚合后再 sum 基本就错了)
revenue_per_customer:人均收入 = SUM(revenue) / COUNT(DISTINCT customer_id)(比率在不同粒度下要重算)
conversion_rate:转化率 = converted_users / eligible_users(分子分母必须在同一粒度计算)
示例 A:Databricks Metric View(YAML)——“比率 + distinct” Databricks 的 metric view 用 YAML 把 measures 和 dimensions 分开定义,引擎在运行时生成正确的聚合计算(查询时用 MEASURE() 显式引用)。下面是一个示意(字段名按你的模型调整即可):
metrics/revenue_metrics.yaml
version: 1 metric_view: name: mv_revenue description: "Revenue metrics with non-additive measures"
source: # 可以是表、视图或 SQL(文档中说明 source 可为 view/table/query) table: main.analytics.fact_orders
dimensions: - name: order_date expr: order_date type: date - name: region expr: region type: string
measures: - name: total_revenue expr: revenue_amount agg: sum description: "Sum of revenue"
- name: distinct_customers
expr: customer_id
agg: count_distinct
description: "Distinct customers"
# 非累加:人均收入(比率)
- name: revenue_per_customer
expr: total_revenue / distinct_customers
agg: ratio
description: "SUM(revenue) / COUNT(DISTINCT customer)"
一键获取完整项目代码
查询时(示意):
SELECT region, MEASURE(revenue_per_customer)AS rev_per_cust FROM main.analytics.mv_revenue GROUPBY region; 这套写法的价值在于:下游换了 group by 粒度,仍然是在“当前粒度”重算比率,而不是对已经算好的比率再做聚合。
(Databricks 文档也强调了 metric view 会把 measure 定义与维度分组分离,用来处理 ratios、distinct counts 这类复杂度量。)
示例 B:dbt Semantic Layer / MetricFlow(YAML)——“可加 vs 非可加” dbt Semantic Layer(MetricFlow)里,一般先定义 semantic_model(entities、dimensions、measures),再定义 metrics。下面示意一个“订单事实表”的语义模型,并定义一个非累加比率指标:
models/semantic/order_semantic.yml
semantic_models:
-
name: orders_semantic model: ref('fct_orders') description: "Order fact semantic model"
entities:
- name: order type: primary expr: order_id
- name: customer type: foreign expr: customer_id
dimensions:
- name: order_date type: time type_params: time_granularity: day
- name: region type: categorical
measures:
-
name: revenue agg: sum expr: revenue_amount
-
name: customers agg: count_distinct expr: customer_id
metrics:
- name: revenue_per_customer description: "SUM(revenue) / COUNT(DISTINCT customer)" type: ratio numerator: measure: revenue denominator: measure: customers 一键获取完整项目代码
两个点值得注意:
customers 用 count_distinct 定义成 measure,避免下游对已聚合结果再聚合
revenue_per_customer 用 type: ratio 明确它是比率指标,执行时按分子/分母在当前粒度计算
示例 C:Snowflake Semantic View(DDL)——“把语义作为 schema-level object” Snowflake 的 semantic view 是数据库里的对象,DDL 会声明 tables、relationships、dimensions/metrics 等。下面是极简示意(语法细节以官方文档为准):
CREATE OR REPLACE SEMANTIC VIEW SALES_SEMANTIC_VIEW tables ( ORDERS primary key (ORDER_ID), CUSTOMERS primary key (CUSTOMER_ID) ) relationships ( ORDERS_TO_CUSTOMERS as ORDERS(CUSTOMER_ID) references CUSTOMERS(CUSTOMER_ID) ) dimensions ( ORDERS.ORDER_DATE as order_date, CUSTOMERS.REGION as region ) metrics ( -- 可加:收入 ORDERS.TOTAL_REVENUE as SUM(ORDERS.REVENUE_AMOUNT),
-- 非累加:去重客户数
ORDERS.DISTINCT_CUSTOMERS as COUNT(DISTINCT ORDERS.CUSTOMER_ID),
-- 非累加:人均收入(比率)
ORDERS.REVENUE_PER_CUSTOMER as
(SUM(ORDERS.REVENUE_AMOUNT) / NULLIF(COUNT(DISTINCT ORDERS.CUSTOMER_ID), 0))
WITH SYNONYMS = ('arpc', 'revenue per customer')
); 一键获取完整项目代码 sql
这种模式的优势主要体现在两点:
语义对象和数据库治理/权限/审计在同一个控制面
同义词(synonyms)这类元数据对 NLQ/Agent 的命中稳定性很有帮助
4.2 业务规则内建:过滤、口径、时间窗 语义定义通常会携带业务规则,比如:
排除测试账号
只统计已完成订单
退款/冲正怎么处理
时间窗:滚动 7 天、自然月、财务季度
这些规则如果散落在报表和脚本里,口径漂移几乎是必然的。把规则放进语义对象本身,复用成本会低很多。
4.3 元数据与语义增强:让“人”和“AI”都能读懂 更偏 AI-ready 的 Semantic View 往往会带这些信息:
指标/维度描述(description)
口径说明(business definition)
owner / steward
认证状态(certified / experimental)
同义词(synonyms)、缩写(acronyms)
展示格式(currency、percent、precision)
示例问法/示例查询(可选)
这些元数据会直接影响:LLM/Agent 能不能稳定选到正确对象。
4.4 治理能力:权限、审计、血缘、影响分析 语义对象进了生产环境,治理能力往往决定它能走多远:
和 catalog 集成(统一资产目录)
行/列级权限、脱敏策略继承
访问审计(谁在何时用哪个指标)
血缘(指标来自哪些表/字段/模型)
影响分析(改一个指标会影响哪些报表/应用/Agent)
4.5 性能能力:物化、增量、缓存、路由 如果语义层只做逻辑抽象,落地后很容易被吐槽“慢”。比较成熟的实现通常会提供:
常用聚合结果缓存
声明式物化(materialization)
增量更新(incremental refresh)
查询重写(query rewriting)与路由
价值在于:把性能优化从“每个报表单独调优”变成“平台级共享优化”。
4.6 多消费面:SQL / API / BI / Agent Semantic View 的消费面不止 BI:
SQL(分析师、Notebook)
JDBC/ODBC(第三方工具)
REST/GraphQL(数据应用、指标服务)
NLQ(自然语言查询)
Agent 工具调用(function calling / tool use)
- 架构:Semantic View 在 AI + 数据平台中的位置 5.1 逻辑分层 一个常见、也比较好沟通的参考分层(从下到上):
Storage / Lakehouse / Warehouse:原始表、明细事实表、维表
Transform / Modeling:数据建模层(星型/雪花)、数据质量、dbt 等
Semantic View(语义视图层):指标/维度/关系/规则/元数据/治理
Serving / Consumption:BI、Notebook、数据应用 API、NLQ、Agent
语义层一般在建模之上,同时尽量靠近平台的治理与目录体系。
5.2 三种主流落地模式(实现路径) 模式 A:平台内原生对象(Platform-native / In-Database) 语义对象作为数据库/平台的一级对象
优点:治理继承强、性能优化空间大、统一入口
挑战:跨平台迁移成本更高,能力边界受平台约束
模式 B:目录/元数据驱动(Catalog-native) 语义定义存储在 catalog(或类似元数据服务)
查询时由引擎做 query rewrite / 生成执行计划
优点:语义与治理紧耦合,天然支持多消费面
挑战:对 catalog 能力和执行引擎的协同要求更高
模式 C:Headless 语义服务(API-first) 语义层是独立服务,对外暴露统一 API 给 BI/应用
优点:工具无关、多平台复用
挑战:治理策略与底层平台的继承需要额外工程;性能优化复杂度也更高
很多团队会混着用:核心指标用平台原生承载,长尾或实验指标用服务化方式接住。
- 一个工程化的语义模型:最小完备要素(MVP) 从 0 开始做语义层,建议先把“最小闭环”跑通。别一上来想覆盖全域,最后容易变成“做了很多定义,但谁也不敢用”。
6.1 实体与关系(Entities & Relationships) 核心事实实体(Fact):订单、账单、事件日志、订阅等
维度实体(Dimension):用户、产品、组织、渠道、时间
关系:外键/业务键/多对多桥表
关系声明的价值很直接:查询生成器/优化器/Agent 不需要靠猜来拼 join。
6.2 指标(Metrics) 一个能长期维护的指标定义,通常会包含:
名称(canonical name)
业务释义(business definition)
计算表达式(aggregation + expression)
粒度(grain):按订单、按用户、按合同等
可切片维度范围(可选):哪些维度组合在治理/性能上更合适
内建过滤(filters):口径规则
时间语义(time):归属日期字段、窗口
格式化(format):货币、百分比、小数位
6.3 维度(Dimensions) 名称与描述
类型:枚举/层级/时间
层级(Hierarchy):类目→子类→SKU、国家→省→市
同义词/别名:服务自然语言、也服务跨团队命名
6.4 语义元数据(Semantic Metadata) owner / domain
certification(生产可用/实验/弃用)
lineage
tags
示例
6.5 权限与策略(Governance) MVP 阶段至少要跑通:
基于角色/用户的访问控制
行/列级策略继承(至少和底层表一致)
审计日志
- Semantic View 的查询方式:从“写 SQL”到“声明式语义查询” 不同实现会提供不同的 query 形态,但共性差不多:
调用方选择 metrics + dimensions
平台负责:
Join 路径解析
过滤规则注入
正确聚合(尤其是 ratio、distinct、semi-additive 指标)
查询重写与加速
7.1 为什么比普通 view 更安全:不可重聚合指标(Non-additive) 典型坑:
distinct_count 很难安全二次聚合
比率类指标(如 sum(revenue)/count(distinct user))在不同粒度下需要重算
语义层把这些东西定义成“度量对象”,执行时由引擎生成正确计算计划,下游只负责选维度与过滤条件。
7.2 一个通用的“语义查询”抽象 可以把语义查询抽象成:
SELECT , FROM <semantic_view> WHERE ...
区别主要有两点:
<semantic_view> 不是明细表
不是简单字段,而是可执行的指标定义
- 面向 AI/Agent:让语义层进入 RAG + Tool 的链路 在 AI + 数据平台里,Semantic View 不只是建模层,它也像一个“结构化业务知识库”。
8.1 语义层如何进入 Agent 的工作流 更稳的问数链路通常是:
意图理解:识别问题里的业务概念(指标、维度、时间范围)
语义检索:从语义层检索候选指标/维度(同义词、描述、认证状态)
权限校验:确认调用者能访问哪些对象
生成语义查询:组合 metrics + dimensions + filters
执行与解释:返回结果,同时引用语义定义说明口径
好处很直观:join、口径、权限这些“最容易出事”的环节由语义对象兜底,模型临场发挥的空间小很多。
8.2 语义层对 AI 额外有价值的元数据 更贴近 AI 使用习惯的字段通常包括:
synonyms:同义词/别名/常见问法
glossary_terms:业务术语词典
guardrails:禁止/限制维度组合(例如不能下钻到个人隐私粒度)
explain_template:解释模板(“口径为…,包含…,不包含…”)
examples:问法→语义查询示例
一句话:Semantic View 既提供“业务语义知识”,也提供“可执行的数据计算接口”。
- 落地经验:怎么把 Semantic View 做成可持续资产 9.1 从少量高价值指标起步 更常见、也更稳的推进方式是:
先选 5–20 个公司级核心指标(财务、增长、留存、转化)
每个指标配套 5–10 个核心维度(时间、地区、产品、渠道、客户分层)
先让这批指标同时跑通:BI + API + NLQ/Agent
再逐步扩展长尾指标
9.2 Core / Edge 分层 一个比较健康的形态是:
Core(核心层):认证指标、标准维度、严格变更流程、影响分析
Edge(边缘层):团队实验指标、临时口径、Agent 专用同义词
Edge 里跑出来的内容,评审通过后再晋升到 Core;Core 的每次变更则尽量保持可追溯。
9.3 Semantics as Code 把语义定义当作代码来管,维护成本会低很多:
PR 评审(业务 + 数据一起看)
自动化测试(指标一致性、数据质量、性能回归)
环境分层(dev/staging/prod)
变更公告与影响分析
9.4 指标测试(Metric Tests)与数据质量 语义层落地时常见“背锅点”是数据质量:指标口径写得再漂亮,底层数据一波动,结果照样不可信。
核心指标一般会配几类测试:
和财务/对账系统的基础一致性测试
异常检测(环比/同比阈值、结构变化)
关键维度覆盖率测试(渠道、地区缺失)
- 常见坑与反模式 把语义层当成“另一个报表层”,指标仍散落在报表里
只做指标,不做关系与维度治理,Agent 还是得猜 join
缺少认证/owner/变更流程,语义对象很快腐化
忽略非可加指标(distinct、ratio),多粒度下算错
只服务 BI,不服务数据应用与 AI,价值被锁死在一个场景
性能策略全靠下游调优,语义层容易被贴上“慢且没用”的标签
- 云器(Yunqi)的 Semantic View 能力与业务实践 11.1 云器语义层的双形态:Lakehouse 原生 + Agent 语义层 云器目前有两套互补的语义层实现:
云器 Lakehouse 语义层(LH 语义层)
原生支持 SQL:可以直接用 SQL 定义与查询语义层对象
通过 MCP 支持 YAML:便于和业界常见的 YAML 语义视图表达对齐(材料中提到“通过 MCP 使用 snowflake yaml 表示 semantic view”)
同时支持 SQL 与 API 查询
DataGPT / Analysis Agent 语义层
最初是为“兼容多种数据源”设计,因此做成独立语义层
提供 AI 辅助生成、管理界面、与索引结合等能力
更偏“智能问数/分析助手”的端到端体验
可以这么理解:
Lakehouse 语义层更像平台级语义资产层(platform-native semantics)
Analysis Agent 语义层更像面向交互与分析链路的语义工作台(agent-native semantics)
11.2 自然语言问数准确率 95%+:云器的实践经验 引入Semantic View的背景:
语义层在自然语言问数场景的核心价值之一,是提升准确率
走语义层问数时,LLM 往往不直接写 SQL,而是“指标/维度/过滤匹配 → 语义层拼接 → SQL”,因此幻觉更低
至于“95%+”,对外表达时建议把评测口径一起讲清楚:评测集是什么、业务域是什么、题型分布如何、是否包含歧义问法等。否则数字很容易被误解。
(1)把 Text-to-SQL 变成 Text-to-Semantics-to-SQL 传统链路:Schema + 知识 + LLM → SQL
语义层链路:指标匹配 + 过滤条件 + 维度选择 + 语义层拼接 → SQL
直观效果:生成空间从“任意 SQL”收敛成“语义组件组合”,每个组件都有明确的定义和边界。
(2)用索引解决歧义:指标/维度/列值的召回 一个典型歧义问题:
“给我看看张三去年七夕和情人节的相关交易额” —— 张三是谁?客户?销售?库管?负责人?
云器的实践做法包括:
指标名称/描述的入库与召回:常用向量索引(并处理长短匹配)
列值召回:常用标量索引(并判断是否需要索引)
知识召回:常用向量索引
材料里也给了 Lakehouse 的索引最佳实践:
语义层 + 索引 这套组合的核心作用,是在问数早期把概念先对齐,尽量别让模型在歧义空间里碰运气。
(3)Dynamic Table / 表外索引:降低对原表改造成本 材料中提到一个用户案例:
用户用语义层问数
通过 dynamic table 在数据表外维护标量索引
现实意义很大:业务表不一定允许频繁加列/加索引,而表外索引通常能更快迭代。
(4)把高频问法沉淀为语义资产 准确率要长期跑稳,还是得靠资产化。高频问题往往会沉淀成:
认证指标(certified metrics)
标准维度(standard dimensions)
内建口径规则(filters)
同义词与解释模板(synonyms / explain template)
这也呼应前文的转变:从“对数”到“对语义资产”。
- 参考实现(不局限于某产品):从“能力点”映射到“实现方式” 下面按能力点概括几条常见实现路径,方便选型/自研时对照。
12.1 语义对象存储 In-DB 对象:语义定义与数据库对象同生命周期
Catalog 对象:语义定义注册在统一目录(含 YAML/JSON/DSL)
Git-as-source:语义定义以代码形式存储,平台负责发布与注册
12.2 查询接口 SQL 扩展(特殊函数/语法)
语义 API(REST/GraphQL)
BI 连接器(JDBC/ODBC + 元数据暴露)
NLQ/Agent 工具接口(tool calling)
12.3 治理集成 与权限系统统一(RBAC/ABAC)
行/列级策略继承
审计:语义对象级访问日志
血缘:从指标追溯到表/字段/作业
12.4 性能策略 结果缓存(query result cache)
声明式预聚合(pre-aggregation)
增量物化(incremental materialization)
查询重写(rewrite)与 cost-based routing
- 总结:Semantic View 是 AI 数据产品化的“中间件” 在 AI + 数据平台语境里,Semantic View 的价值可以概括成一句话:
把组织对业务的理解,变成机器可执行、可治理、可复用的“真相接口”。
没有语义层时:
指标口径在工具间漂移
LLM/Agent 需要猜表、猜字段、猜 join、猜过滤
数据治理很难扩展到所有消费面
语义层成熟后:
指标定义一次,跨 BI / 应用 / AI 复用
口径、权限、审计、血缘与语义绑定
AI 更像在“调用语义接口”,而不是临场拼 SQL