引言
数据建模是数据仓库与数据平台建设的基石。选择合适的建模方法,不仅决定了数据存储的效率和查询的性能,更深刻影响着数据团队的协作方式、业务需求的响应速度以及系统的长期可演进性。
数据建模方法可分为两个层次:
第一层:正式方法论(Methodology)------拥有完整理论体系、专著和社区,适用于数仓的全局设计:
- E-R 模型 / 关系建模(3NF):源于 Bill Inmon 的企业级数仓理念,追求数据的规范化与一致性
- 维度建模(Dimensional Modeling):由 Ralph Kimball 提出,以业务过程为导向,面向分析查询优化
- Data Vault:由 Dan Linstedt 创建,专注于企业数据仓库的审计追踪与历史留存
- Anchor Modeling:由 Lars Rönnbäck 提出,追求极致规范化(6NF),实现属性级别的独立演进
- 阿里 OneData:阿里巴巴沉淀的数仓方法论,以统一规范、统一建模、统一指标为核心
第二层:建模模式(Pattern)------特定场景下的实践模式,通常在方法论指导下应用于局部:
- OBT / 宽表模式:以查询简约为导向的打平策略
- Activity Schema:以活动为核心原语的事件分析模式
- 图建模:以节点-边-属性为核心的关系网络建模
- 时序建模:以度量-标签-时间戳为核心的时序数据建模
此外,领域驱动数据建模在 Data Mesh 架构下正在兴起,推动从"集中式建模"到"领域自治建模"的范式转变。
本文将系统讲解上述方法论与建模模式的核心思想、模型结构、设计要点与适用场景,帮助你在实际项目中做出合理选择。
一、E-R 模型 / 关系建模(3NF)
1.1 核心思想
E-R 模型(Entity-Relationship Model)由 Peter Chen 于 1976 年提出,将现实世界抽象为"实体"、"属性"和"关系"三大要素。关系建模的理论基础则是 Edgar F. Codd 提出的关系模型与范式理论。在数仓语境下,E-R 模型通常以**第三范式(3NF)**落地,即消除非主属性对候选键的传递函数依赖,确保每个非键属性只依赖于主键。
Bill Inmon 在《Building the Data Warehouse》中倡导以 3NF 构建企业级数据仓库(EDW),核心理念是:
数据仓库应该是企业唯一的、集成的、面向主题的、非易失的、随时间变化的数据集合,而 3NF 是保证数据一致性和非冗余的最佳方式。
因此,E-R 模型与 3NF 在数仓领域常被交替使用,但严格来说,E-R 是建模语言,3NF 是规范化级别。
1.2 范式层级回顾
| 范式 | 规则 | 示例 |
|---|---|---|
| 1NF | 属性不可再分(原子性) | 拆分"姓名"为"姓"和"名" |
| 2NF | 消除部分函数依赖 | 订单明细中商品名称不应依赖订单号的部分键 |
| 3NF | 消除传递函数依赖 | 客户所在城市不应通过邮编间接依赖客户ID |
| BCNF | 每个决定因素都是候选键 | 进一步消除主属性间的依赖 |
1.3 模型结构
3NF 模型的典型特征:
- 实体与关系分离:每个业务实体独立成表,通过外键关联
- 无数据冗余:同一份数据只存储一次,减少更新异常
- 层次扁平:不刻意构建星型或雪花结构,表与表之间呈网状关系
以电商场景为例,3NF 模型可能包含以下实体表:
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ customer │────<│ orders │>────│ employee │
└──────────┘ └──────────────┘ └──────────┘
│
│
┌──────────────┐ ┌──────────┐
│ order_items │>────│ product │
└──────────────┘ └──────────┘
│
┌──────────┐
│ category │
└──────────┘
1.4 优点与局限
优点:
- 数据一致性高,无冗余带来的更新异常
- 适合作为企业级单一数据源(Single Source of Truth)
- 模型扩展性好,新增实体和关系对现有结构影响小
- 适合 E-R 建模工具进行正向工程,自动生成 DDL
局限:
- 查询复杂度高,分析型查询往往需要多表 JOIN
- 面向业务人员不友好,理解成本高
- 建设周期长,需全面梳理企业数据模型后方可落地
- 对快速变化的业务需求响应较慢
1.5 适用场景
| 场景 | 说明 |
|---|---|
| 企业级数据仓库(EDW) | Inmon 架构中的核心仓库层,作为全企业唯一数据源 |
| 主数据管理(MDM) | 需要保证主数据一致性和准确性的场景 |
| 监管与合规 | 对数据准确性要求极高,不允许冗余导致的不一致 |
| 数据集成枢纽 | 多源系统数据整合的中间层,强调集成而非查询性能 |
二、维度建模
2.1 核心思想
维度建模由 Ralph Kimball 在《The Data Warehouse Toolkit》中系统提出,其核心理念是:
以业务过程为驱动,围绕"谁、什么、何时、何地、为什么、如何"构建直观的星型模型,让业务用户能够直接理解和查询数据。
维度建模将数据分为两大类:
- 事实(Fact):对业务过程的度量,通常是可计算的数值(如销售额、订单数)
- 维度(Dimension):描述事实的上下文,提供分析的视角(如时间、地域、产品)
2.2 四步建模法
Kimball 在《The Data Warehouse Toolkit》中提出了经典的四步建模法 ,这是维度建模的核心实践流程。四个步骤必须严格按序执行,其中声明粒度是最关键也最容易被忽视的一步。
第一步:选择业务过程(Select the Business Process)
业务过程是组织中完成的操作型活动,是维度建模的起点。选择业务过程需要回答"我们在度量什么活动":
- 业务过程是一个动词短语,而非名词(如"处理订单"而非"订单")
- 每个业务过程对应企业总线矩阵中的一行
- 同一业务过程不应拆分到多个事实表中
| 业务过程 | 说明 | 典型事实表 |
|---|---|---|
| 处理订单 | 客户下单购买商品 | 销售事务事实表 |
| 处理支付 | 客户完成支付 | 支付事务事实表 |
| 管理库存 | 每日盘点库存状态 | 库存快照事实表 |
| 履约订单 | 订单从下单到签收全流程 | 订单履约累积快照事实表 |
第二步:声明粒度(Declare the Grain)
粒度确定事实表中每一行代表什么,是四步建模法中最关键的一步。Kimball 强调:
粒度必须在确定维度和事实之前声明。如果跳过这一步,维度和事实的讨论将失去锚点,导致模型混乱。
粒度声明的核心原则:
-
优先选择最细粒度(Atomic Grain):最细粒度能回答最多的问题,聚合粒度会限制分析灵活性
-
同一事实表不能混用多种粒度:不同粒度应拆分为不同的事实表
-
粒度等价于事实表的逻辑主键:粒度声明实际上定义了事实表的主键构成
粒度声明示例:
✅ "销售事实表中每行代表一个交易行项目(一笔交易中的一个商品)"
✅ "库存快照事实表中每行代表某天某仓库某商品的库存状态"
❌ "销售事实表中每行代表一笔交易或一个商品"(粒度不明确)
第三步:确定维度(Identify the Dimensions)
粒度确定后,维度自然浮现------维度是"谁、什么、何时、何地、为什么、如何"的上下文:
| 维度 | 对应问题 | 示例 |
|---|---|---|
| 日期维度 | 何时 | 下单日期、支付日期 |
| 产品维度 | 什么 | 商品名称、分类、品牌 |
| 客户维度 | 谁 | 客户名称、等级、区域 |
| 门店维度 | 何地 | 门店名称、城市、省份 |
| 促销维度 | 为什么 | 促销类型、折扣力度 |
| 销售员维度 | 如何 | 销售员姓名、团队 |
第四步:确定事实(Identify the Facts)
事实是粒度级别上的数值度量,必须与声明的粒度严格一致:
- 事实必须是可计算的数值(可加、半可加或不可加)
- 事实必须与粒度匹配------如果粒度是"交易行项目",则"订单总金额"不属于该粒度
- 事实表中不应包含文本类描述性信息(应放入维度表)
| 事实类型 | 说明 | 示例 |
|---|---|---|
| 可加事实 | 可沿所有维度自由聚合 | 销售额、销售数量 |
| 半可加事实 | 可沿部分维度聚合,但不能沿时间聚合 | 账户余额、库存量 |
| 不可加事实 | 不能沿任何维度直接聚合 | 比率、百分比(需转换为可加分量存储) |
四步法完整示例(电商销售场景):
步骤一:选择业务过程 → "处理销售交易"
步骤二:声明粒度 → "每行代表一笔交易中的一个商品项"
步骤三:确定维度 → 日期、产品、客户、门店、促销
步骤四:确定事实 → 销售数量、销售金额、折扣金额、毛利
2.3 事实表类型
| 类型 | 说明 | 示例 |
|---|---|---|
| 事务事实表 | 记录业务事件,一行对应一次事务 | 订单事实、支付事实 |
| 周期快照事实表 | 按固定时间间隔记录状态 | 每日库存快照、月度账户余额 |
| 累积快照事实表 | 记录业务流程的多个里程碑 | 订单履约事实(下单→发货→签收) |
| 无事实事实表 | 仅记录维度关联,无度量值 | 学生选课事实(学生-课程-学期) |
2.4 维度表设计要点
缓慢变化维度(SCD) 是维度建模的核心问题之一:
| SCD 类型 | 策略 | 适用场景 |
|---|---|---|
| Type 1 | 直接覆盖旧值 | 不需要历史追踪,如纠错 |
| Type 2 | 新增行,用起止时间标记有效期 | 需要完整历史追踪,最常用 |
| Type 3 | 新增列保存前一个值 | 只需追踪前一次变更 |
| Type 4 | 历史数据单独存入历史表 | 历史数据量大,需分离存储 |
| Type 6 | Type 1 + 2 + 3 组合 | 复杂场景,较少使用 |
其他维度设计模式:
- 退化维度(Degenerate Dimension):没有独立维度表的事实表属性,如订单号
- 角色扮演维度(Role-Playing Dimension):同一维度表在事实表中多次出现,如订单日期与发货日期都引用日期维度
- 杂项维度(Junk Dimension):将低基数的标志位和指示器组合到一个维度表中
- 一致性维度(Conformed Dimension):跨多个数据集市共享的标准维度,是 Kimball 总线架构的关键
2.5 星型模型与雪花模型
星型模型(Star Schema) 雪花模型(Snowflake Schema)
┌────────┐ ┌────────┐
│ 时间维度│ │ 时间维度│
└───┬────┘ └───┬────┘
│ │
┌───────┴────────┐ ┌─────────┴─────────┐
│ 销售事实表 │ │ 销售事实表 │
└───────┬────────┘ └─────────┬─────────┘
┌────┼────┐ ┌──────┼──────┐
│ │ │ │ │ │
┌──┴─┐┌─┴──┐┌┴────┐ ┌────┴──┐┌──┴───┐┌─┴────┐
│产品││门店 ││客户 │ │产品 ││门店 ││客户 │
└────┘└────┘└─────┘ └───┬───┘└──────┘└──┬───┘
│ │
┌───┴───┐ ┌───┴───┐
│产品分类│ │客户区域│
└───────┘ └───────┘
| 对比项 | 星型模型 | 雪花模型 |
|---|---|---|
| 维度结构 | 扁平,不规范化 | 层次化,规范化 |
| JOIN 数量 | 少 | 多 |
| 查询性能 | 更优 | 较差 |
| 存储空间 | 有冗余 | 更节省 |
| 可读性 | 高 | 较低 |
| 实践选择 | 主流选择 | 特殊场景使用 |
2.6 Kimball 总线架构
Kimball 方法论强调通过**总线架构(Bus Architecture)**逐步构建数据仓库:
-
定义企业级一致性维度(Conformed Dimensions)
-
按业务过程逐个构建数据集市(Data Mart)
-
通过共享一致性维度实现数据集市的集成
-
最终形成企业级数据仓库
一致性维度 ┌──────────────┐ │ 时间 地域 │ │ 产品 客户 │ └──┬───┬───┬───┘ │ │ │ ┌─────────┤ │ ├─────────┐ ▼ ▼ │ ▼ ▼ ┌──────────┐ ┌─────┴──────┐ ┌──────────┐ │ 销售集市 │ │ 库存集市 │ │ 采购集市 │ └──────────┘ └────────────┘ └──────────┘
2.7 优点与局限
优点:
- 直观易懂,业务人员可直接理解和使用
- 查询性能优异,星型 JOIN 简单高效
- 建设周期短,可按业务过程迭代交付
- 与 BI 工具天然契合,拖拽式分析友好
局限:
- 数据冗余,维度表存在大量重复信息
- 维度变更处理复杂,SCD Type 2 导致数据膨胀
- 跨业务过程的一致性维度维护成本高
- 不适合频繁的源系统结构变更
2.8 适用场景
| 场景 | 说明 |
|---|---|
| 数据集市 / 分析应用 | 面向特定业务线的分析场景,如销售分析、用户行为分析 |
| BI 报表与可视化 | Tableau、Power BI 等 BI 工具的最佳搭档 |
| 实时/近实时分析 | 事实表追加写入,查询高效 |
| 数据湖仓的 Serving 层 | 湖仓架构中面向查询的汇总层 |
| 快速迭代的业务场景 | 敏捷数仓建设,小步快跑 |
三、Data Vault 建模
3.1 核心思想
Data Vault 由 Dan Linstedt 在 2000 年提出,并于 2013 年公开发表。其核心理念是:
构建一个可审计、可追溯、可扩展的企业数据仓库,完整保留历史数据,同时将业务键的变更历史与描述性属性的变更历史分离管理。
Data Vault 的三大设计原则:
- 可审计性(Auditability):每条记录都有加载时间和数据来源,可追溯至源系统
- 可扩展性(Scalability):新增源系统或业务实体只需新增表,不影响现有结构
- 灵活性(Agility):业务规则延迟到信息层应用,原始层保持与源系统一致
3.2 三大核心表类型
Hub(枢纽表)
存储业务键(Business Key),代表一个唯一的业务实体。Hub 表只包含业务键和加载元数据,不存储描述性属性。
sql
CREATE TABLE hub_customer (
hk_customer BINARY(16) NOT NULL,
bk_customer_id VARCHAR(20) NOT NULL,
load_date TIMESTAMP NOT NULL,
record_source VARCHAR(100) NOT NULL,
PRIMARY KEY (hk_customer)
);
Link(链接表)
存储实体之间的关系,相当于关联表/交叉表。Link 表记录两个或多个 Hub 之间的关联关系。
sql
CREATE TABLE link_order_customer (
hk_link_order_customer BINARY(16) NOT NULL,
hk_order BINARY(16) NOT NULL,
hk_customer BINARY(16) NOT NULL,
load_date TIMESTAMP NOT NULL,
record_source VARCHAR(100) NOT NULL,
PRIMARY KEY (hk_link_order_customer)
);
Satellite(卫星表)
存储 Hub 或 Link 的描述性属性及历史变更。每个卫星表通过哈希键关联到 Hub 或 Link,并通过加载时间戳维护历史版本。
sql
CREATE TABLE sat_customer_details (
hk_customer BINARY(16) NOT NULL,
load_date TIMESTAMP NOT NULL,
load_end_date TIMESTAMP,
record_source VARCHAR(100) NOT NULL,
customer_name VARCHAR(200),
customer_email VARCHAR(200),
customer_phone VARCHAR(50),
city VARCHAR(100),
hash_diff BINARY(16),
PRIMARY KEY (hk_customer, load_date)
);
3.3 模型结构示意
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ hub_customer │ │ hub_order │ │ hub_product │
│ ────────────── │ │ ────────────── │ │ ────────────── │
│ hk_customer │ │ hk_order │ │ hk_product │
│ bk_customer_id │ │ bk_order_no │ │ bk_product_id │
│ load_date │ │ load_date │ │ load_date │
│ record_source │ │ record_source │ │ record_source │
└───────┬──────────┘ └───────┬──────────┘ └───────┬──────────┘
│ │ │
┌────┴─────┐ ┌────┴──────┐ ┌─────┴────┐
│ │ │ │ │ │
┌──┴───────┐ ┌┴──────────┐│ ┌────────┴──────┐ ┌───┴───────┐ │
│sat_cust │ │sat_cust ││ │link_order_cust│ │sat_product│ │
│_name │ │_contact ││ │──────────────│ │_details │ │
└──────────┘ └───────────┘│ │hk_link_o_c │ └───────────┘ │
│ │hk_order │ │
│ │hk_customer │ │
└──┤load_date │ │
│record_source │ │
└──────────────┘ │
│
┌──────────────────┐ │
│link_order_product│ │
│──────────────────│ │
│hk_link_o_p │ │
│hk_order │◄──────────┘
│hk_product │
│load_date │
│record_source │
└──────────────────┘
3.4 Data Vault 2.0 扩展
Data Vault 2.0 在 1.0 基础上引入了以下关键扩展:
| 扩展 | 说明 |
|---|---|
| 业务键哈希(Hash Key) | 使用 MD5/SHA-1 对业务键哈希,替代顺序主键,支持多源系统集成 |
| 哈希差异(Hash Diff) | 对卫星表属性计算哈希,快速检测变更,避免全量字段比对 |
| 敏捷方法论 | 引入 Scrum/Kanban 等敏捷实践,按迭代交付 |
| 多源系统支持 | 同一 Hub 可整合多个源系统的同一业务实体 |
| PIT 表(Point-in-Time) | 按时间点快速定位卫星表的有效记录,避免多卫星 JOIN 时的时间对齐问题 |
| Bridge 表 | 预计算的层级关系桥接表,用于加速层级遍历查询 |
PIT 表示例:
sql
CREATE TABLE pit_customer (
hk_customer BINARY(16) NOT NULL,
snapshot_date DATE NOT NULL,
hk_sat_cust_name BINARY(16),
hk_sat_cust_contact BINARY(16),
load_date TIMESTAMP NOT NULL,
PRIMARY KEY (hk_customer, snapshot_date)
);
3.5 加载模式
Data Vault 的加载遵循严格的规则:
| 表类型 | 加载方式 | 说明 |
|---|---|---|
| Hub | 仅插入 | 新业务键追加,已有业务键跳过 |
| Link | 仅插入 | 新关系追加,已有关系跳过 |
| Satellite | 仅插入 | 属性变更时追加新行(通过 Hash Diff 检测变更) |
这种"只追加"模式确保了完整的历史可追溯性。
3.6 优点与局限
优点:
- 完整的审计追踪,每条记录可溯源至源系统和加载时间
- 极强的可扩展性,新增源系统或实体只需新增表
- 业务规则延迟应用,原始层稳定可靠
- 并行加载友好,Hub/Link/Satellite 可独立并行加载
- 适合大规模数据集成场景
局限:
- 查询复杂度高,需要多表 JOIN(Hub + Link + 多个 Satellite)
- 学习曲线陡峭,团队需要专门培训
- 直接面向业务查询性能差,需要额外的信息层(Information Mart)或视图
- 模型表数量多,元数据管理复杂
- 对小型项目而言过于重量级
3.7 适用场景
| 场景 | 说明 |
|---|---|
| 大型企业级数据仓库 | 多源系统、多业务线的数据整合 |
| 监管与合规 | 金融、医疗等对数据审计有严格要求的行业 |
| 历史数据留存 | 需要完整保留所有历史变更的场景 |
| M&A 数据整合 | 企业并购后需要快速整合异构数据源 |
| 数据湖仓的 Raw 层 | 湖仓架构中保留原始数据的层,确保可追溯 |
四、Anchor Modeling
4.1 核心思想
Anchor Modeling 由 Lars Rönnbäck 和 Olle Regardt 在 2009 年提出,并于 2014 年发表正式学术论文。其核心理念是:
将数据模型分解到极致的规范化程度(6NF),让每个属性都能独立演进,从而实现最大的灵活性和最小的变更影响范围。
Anchor Modeling 可视为 Data Vault 的进一步规范化演进。Data Vault 将属性分组到卫星表中,而 Anchor Modeling 将每个属性都独立为一张表,彻底消除属性间的耦合。
4.2 四大核心表类型
Anchor(锚表)
等价于 Data Vault 的 Hub,存储业务键,代表唯一业务实体。
sql
CREATE TABLE AC_CUSTOMER (
AC_CUSTOMER_ID BINARY(16) NOT NULL,
CUSTOMER_BK VARCHAR(20) NOT NULL,
PRIMARY KEY (AC_CUSTOMER_ID)
);
Attribute(属性表)
每个描述性属性独立为一张表,这是 Anchor Modeling 与 Data Vault 的核心区别。每个属性表只存储一个业务属性及其历史变更。
sql
CREATE TABLE AT_CUSTOMER_NAME (
AC_CUSTOMER_ID BINARY(16) NOT NULL,
CUSTOMER_NAME VARCHAR(200) NOT NULL,
VALID_FROM TIMESTAMP NOT NULL,
PRIMARY KEY (AC_CUSTOMER_ID, VALID_FROM)
);
CREATE TABLE AT_CUSTOMER_EMAIL (
AC_CUSTOMER_ID BINARY(16) NOT NULL,
CUSTOMER_EMAIL VARCHAR(200) NOT NULL,
VALID_FROM TIMESTAMP NOT NULL,
PRIMARY KEY (AC_CUSTOMER_ID, VALID_FROM)
);
Tie(纽带表)
等价于 Data Vault 的 Link,存储实体之间的关系。
sql
CREATE TABLE TI_ORDER_CUSTOMER (
AC_ORDER_ID BINARY(16) NOT NULL,
AC_CUSTOMER_ID BINARY(16) NOT NULL,
VALID_FROM TIMESTAMP NOT NULL,
PRIMARY KEY (AC_ORDER_ID, AC_CUSTOMER_ID, VALID_FROM)
);
Knot(结表)
存储静态的、可复用的枚举值(如状态码、类型码),避免在多个属性表中重复存储相同的枚举值。
sql
CREATE TABLE KN_STATUS (
KN_STATUS_ID BINARY(16) NOT NULL,
STATUS_VALUE VARCHAR(50) NOT NULL,
PRIMARY KEY (KN_STATUS_ID)
);
4.3 模型结构示意
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ AC_CUSTOMER │ │ AC_ORDER │ │ AC_PRODUCT │
│ (Anchor) │ │ (Anchor) │ │ (Anchor) │
└───┬────┬───┬───┘ └───────┬────────┘ └───────┬────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌──────┐┌──────┐┌──────┐ ┌──────────┐ ┌──────────┐
│AT_C ││AT_C ││AT_C │ │TI_ORDER │ │AT_PROD │
│_NAME ││_EMAIL││_CITY │ │_CUSTOMER │ │_NAME │
│(Attr)││(Attr)││(Attr)│ │(Tie) │ │(Attr) │
└──────┘└──────┘└──────┘ └──────────┘ └──────────┘
│
┌──────────┐
│TI_ORDER │
│_PRODUCT │
│(Tie) │
└──────────┘
┌────────────────┐
│ KN_STATUS │
│ (Knot) │
│ ──────────── │
│ STATUS_VALUE │
│ "active" │
│ "inactive" │
│ "suspended" │
└────────────────┘
4.4 与 Data Vault 的关键区别
| 对比维度 | Data Vault | Anchor Modeling |
|---|---|---|
| 规范化程度 | 3NF(Hub/Link)+ 非规范(Satellite) | 6NF(全部极致规范化) |
| 属性组织 | 分组到 Satellite 表中 | 每个属性独立成表 |
| 变更影响范围 | Satellite 级别(一组属性) | 属性级别(单个属性) |
| 表数量 | 多 | 极多 |
| 查询复杂度 | 高 | 极高 |
| 历史追踪 | Satellite 级别 | 属性级别,更精细 |
| 枚举值处理 | 嵌入 Satellite 或独立维度 | Knot 表统一管理 |
| 理论基础 | 实践驱动 | 学术论文支撑 |
4.5 优点与局限
优点:
- 极致的灵活性,任何单属性的变更不影响其他属性
- 完全消除属性间耦合,模型演进零副作用
- 精确到属性级别的历史追踪
- Knot 表消除枚举值冗余
- 适合属性变更频率差异极大的场景
局限:
- 表数量爆炸,一个有 50 个属性的实体会产生 50+ 张属性表
- 查询极其复杂,获取一个实体的完整视图需要大量 JOIN
- 必须依赖视图层或虚拟化层来提供可用的查询接口
- 工具链和社区支持远不如 Data Vault 成熟
- 对团队建模能力要求极高
4.6 适用场景
| 场景 | 说明 |
|---|---|
| 属性变更频率差异大 | 部分属性频繁变更,部分几乎不变,需要独立管理 |
| 极致规范化要求 | 对数据冗余零容忍的场景 |
| 学术研究 / 前沿实践 | 对建模理论有深度追求的团队 |
| 北欧金融行业 | Anchor Modeling 在瑞典等北欧金融行业有成熟实践 |
五、阿里 OneData 方法论
5.1 核心思想
OneData 是阿里巴巴在多年大数据实践中沉淀的数仓方法论,其核心理念是:
统一规范、统一建模、统一指标------通过规范化的分层架构和指标体系,解决大数据时代"数据孤岛、指标口径不一致、重复建设"三大顽疾。
OneData 不是一种独立的建模技术(如星型模型或 Data Vault),而是一套涵盖规范、分层、建模和指标治理的完整方法论体系。它在建模层面主要采用维度建模,但将维度建模的实践提升到了企业级治理的高度。
5.2 核心原则
| 原则 | 说明 |
|---|---|
| 统一规范 | 命名规范、开发规范、流程规范全团队统一 |
| 统一建模 | 相同业务过程只建一次模型,避免重复建设 |
| 统一指标 | 同一业务含义的指标只定义一次,全公司复用 |
5.3 分层架构
OneData 方法论定义了经典的数仓分层体系,这一分层已成为国内互联网行业的事实标准:
┌─────────────────────────────────────────────────────────────┐
│ ADS(Application Data Service)应用数据服务层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 面向应用的宽表、指标表、推荐特征表 │ │
│ │ 直接服务报表、数据产品、API │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ DWS(Data Warehouse Summary)汇总数据层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 按主题域汇总的轻度聚合表 │ │
│ │ 如:用户每日汇总表、商品每日汇总表 │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ DWD(Data Warehouse Detail)明细数据层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 清洗、标准化后的明细事实表 │ │
│ │ 采用维度建模,星型模型 │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ ODS(Operational Data Store)操作数据层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 贴源同步,保持源系统结构 │ │
│ │ 不做业务逻辑转换,可增加分区和增量标记 │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ DIM(Dimension)公共维度层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 一致性维度表,贯穿 DWD/DWS/ADS │ │
│ │ 如:时间维度、地域维度、用户维度、商品维度 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
5.4 主题域划分
OneData 强调按**主题域(Subject Area)**组织数据,主题域是对业务过程的抽象归类:
| 主题域 | 包含的业务过程 | 典型事实表 |
|---|---|---|
| 交易域 | 下单、支付、退款 | 交易明细事实表 |
| 用户域 | 注册、登录、活跃 | 用户行为事实表 |
| 商品域 | 发布、上下架、价格变更 | 商品变更事实表 |
| 营销域 | 优惠券发放、领券、核销 | 营销活动事实表 |
| 物流域 | 发货、配送、签收 | 物流轨迹事实表 |
5.5 指标体系治理
OneData 的核心创新之一是指标体系治理,将指标分为三类:
| 指标类型 | 说明 | 示例 |
|---|---|---|
| 原子指标 | 对业务过程的度量,不可再分 | 支付金额、订单数 |
| 派生指标 | 原子指标 + 修饰词 + 时间周期 | 近 7 天北京地区支付金额 |
| 复合指标 | 由多个原子/派生指标计算得出 | 客单价 = 支付金额 / 支付笔数 |
指标命名规范:
[时间周期][修饰词][原子指标]
示例:
trd_07d_beijing_pay_amt → 近7天北京地区支付金额
usr_1d_login_cnt → 近1天登录次数
5.6 建模流程
OneData 的建模流程强调"自顶向下设计,自底向上实施":
- 规范定义:制定命名规范、开发规范、指标规范
- 主题域划分:按业务线划分主题域,明确边界
- 总线矩阵设计:定义一致性维度和业务过程的关系矩阵
- 明细模型设计:DWD 层按维度建模设计星型模型
- 汇总模型设计:DWS 层按主题域设计轻度聚合表
- 指标定义与开发:基于原子指标派生指标体系
- 应用模型设计:ADS 层按应用场景设计宽表
5.7 优点与局限
优点:
- 解决指标口径不一致的顽疾,统一指标定义
- 分层清晰,职责明确,降低认知成本
- 一致性维度确保跨主题域的数据一致性
- 规范化命名和流程,降低团队协作成本
- 已在国内互联网行业广泛验证,人才储备丰富
局限:
- 规范落地依赖组织执行力,小团队难以严格执行
- 分层过多可能导致开发效率下降(尤其是简单需求)
- 指标治理需要持续投入,容易"破窗"
- 更适合中大型团队,小团队可能觉得过重
- 对实时场景的支持需要额外设计
5.8 适用场景
| 场景 | 说明 |
|---|---|
| 中大型互联网公司 | 数仓团队 10 人以上,多业务线并行 |
| 指标口径治理 | 指标口径混乱,急需统一的场景 |
| 离线数仓建设 | 以离线批处理为主的数据平台 |
| 电商 / 交易类业务 | OneData 的原生场景,最成熟 |
| 国内企业 | 国内大数据生态下最通用的方法论 |
六、建模模式(Pattern)
方法论提供全局设计框架,而建模模式提供特定场景下的局部实践策略。以下模式可在任何方法论指导下灵活应用。
6.1 OBT / 宽表模式
One Big Table(OBT) 将事实和所有维度属性打平为一张大宽表,牺牲存储空间换取查询简单性。
┌──────────────────────────────────────────────────────────────┐
│ 销售宽表(dws_sales_daily) │
│──────────────────────────────────────────────────────────────│
│ 日期 | 产品ID | 产品名 | 分类 | 品牌 | 门店ID | 门店名 | │
│ 城市 | 区域 | 销售额 | 销售量 | 客单价 | ... │
└──────────────────────────────────────────────────────────────┘
| 优点 | 局限 |
|---|---|
| 查询极简,无需 JOIN | 数据冗余严重 |
| 列存引擎压缩率高 | 更新代价大 |
| 适合自助分析 | 维度变更需全量刷新 |
| 与 BI 工具高度契合 | 不适合高频更新场景 |
适用场景: ClickHouse/Doris 等列存引擎上的指标看板、自助分析平台、实时大屏
6.2 Activity Schema
由 Maxime Beauchemin(Apache Superset 创始人)提出,以**活动(Activity)**为核心原语。每条记录描述一个实体在某个时间点发生的活动,类似事务事实表但更抽象,强调活动的组合与排序分析。
核心结构:
┌─────────────────────────────────────────────────────┐
│ activity_stream │
│─────────────────────────────────────────────────────│
│ entity_id | 活动主体标识(用户ID、设备ID等) │
│ activity | 活动类型(login、purchase、click等) │
│ activity_ts | 活动时间戳 │
│ attributes | 活动属性(JSON / 结构化字段) │
│ feature_1 | 预计算特征 │
│ feature_2 | 预计算特征 │
└─────────────────────────────────────────────────────┘
与维度建模的区别:
| 对比维度 | 维度建模 | Activity Schema |
|---|---|---|
| 核心原语 | 事实 + 维度 | 实体 + 活动 |
| 模型结构 | 多表(事实表 + 维度表) | 单表(活动流) |
| 分析方式 | 切片、切块、下钻 | 活动序列、漏斗、路径 |
| 灵活性 | 需预定义维度 | 活动类型可动态扩展 |
适用场景: 产品分析、用户行为分析、漏斗与路径分析
6.3 图建模
图建模以**节点(Node)、边(Edge)、属性(Property)**为核心原语,用于建模实体之间的复杂关系网络。与关系型建模是根本不同的范式。
核心结构:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Person │───>│ Transfer │───>│ Person │
│ Node │ │ Edge │ │ Node │
└──────────┘ └──────────┘ └──────────┘
节点属性:id, name, age, risk_level
边属性:amount, timestamp, channel
与关系建模的本质区别:
| 对比维度 | 关系建模 | 图建模 |
|---|---|---|
| 核心原语 | 表、行、列、外键 | 节点、边、属性 |
| 关系表达 | 隐式(外键 JOIN) | 显式(边直接连接) |
| 多跳查询 | 递归 JOIN,性能差 | 原生图遍历,性能优 |
| 数据模型 | 二维表格 | 属性图 / RDF |
| 典型引擎 | PostgreSQL, Spark | Neo4j, NebulaGraph, TigerGraph |
适用场景: 风控关系网络、社交网络分析、知识图谱、反欺诈、推荐系统
6.4 时序建模
时序建模以**度量(Metric)、标签(Tag/Label)、时间戳(Timestamp)**为核心原语,专为时间序列数据优化。
核心结构:
┌─────────────────────────────────────────────────────┐
│ 时序数据点 │
│─────────────────────────────────────────────────────│
│ metric_name | 指标名称(cpu_usage, temperature) │
│ tags | 标签键值对(host=web01, region=us) │
│ timestamp | 时间戳(纳秒精度) │
│ value | 度量值(float64) │
└─────────────────────────────────────────────────────┘
设计要点:
| 要点 | 说明 |
|---|---|
| 高基数标签控制 | 避免标签值过多导致时间线爆炸 |
| 数据降采样 | 历史数据按时间粒度聚合,节省存储 |
| 冷热分层 | 近期数据热存储,历史数据冷存储 |
| 数据保留策略 | 按业务需求设置 TTL |
与维度建模的关系: 时序建模可视为维度建模在时序场景的特化------度量等价于事实,标签等价于维度,时间戳是隐含的核心维度。但时序建模更强调写入吞吐、降采样和保留策略。
适用场景: IoT 设备监控、APM 应用性能监控、金融行情数据、运维指标监控
七、领域驱动数据建模(Data Mesh 语境)
7.1 核心思想
Data Mesh 由 Zhamak Dehghani 在 2019 年提出,虽然它首先是架构模式,但它深刻影响了数据建模的实践方式。其核心理念是:
将数据视为产品,由领域团队自治管理,而非由中心化数据团队统一建模。
7.2 对建模实践的影响
| 传统集中式建模 | Data Mesh 语境下的建模 |
|---|---|
| 中心化团队统一建模 | 领域团队自治建模 |
| 全局一致性维度 | 领域内一致性 + 跨域联邦标准 |
| 单一数仓模型 | 每个领域独立设计数据产品 |
| 自顶向下设计 | 领域驱动设计(DDD) |
| 集中式治理 | 联邦式治理 + 平台自助 |
7.3 数据产品建模
在 Data Mesh 中,每个数据产品需要明确:
- 数据产品接口:Schema、SLA、 freshness
- 领域事件:领域内的核心业务事件
- 领域实体:领域内的核心业务实体
- 跨域契约:与其他领域的数据交换协议
7.4 适用场景
| 场景 | 说明 |
|---|---|
| 大型组织多业务线 | 各业务线独立演进,无法等待中心化团队 |
| 领域边界清晰 | 可按 DDD 划分限界上下文 |
| 数据平台成熟 | 具备自助数据平台基础设施 |
| 组织去中心化 | 领域团队有数据工程能力 |
八、方法论全景对比
8.1 五大方法论核心对比
| 对比维度 | E-R/3NF | 维度建模 | Data Vault | Anchor Modeling | OneData |
|---|---|---|---|---|---|
| 提出者 | Inmon | Kimball | Linstedt | Rönnbäck | 阿里巴巴 |
| 核心目标 | 数据一致性 | 查询性能与易用性 | 审计追踪与可扩展性 | 极致灵活与属性独立 | 规范统一与指标治理 |
| 驱动方式 | 主题域驱动 | 业务过程驱动 | 业务键驱动 | 业务键 + 属性驱动 | 主题域 + 指标驱动 |
| 规范化程度 | 高(3NF) | 低(星型) | 中 | 极高(6NF) | 中(DWD 星型 + DWS 聚合) |
| 查询复杂度 | 高 | 低 | 高 | 极高 | 低 |
| 历史追踪 | 需额外设计 | SCD 机制 | 原生支持 | 原生支持(属性级) | SCD + 快照 |
| 可扩展性 | 中 | 中 | 高 | 极高 | 中 |
| 建设周期 | 长 | 短 | 中 | 长 | 中 |
| 学习曲线 | 中 | 低 | 高 | 极高 | 中 |
| 数据冗余 | 低 | 高 | 中 | 极低 | 中 |
| 业务友好度 | 低 | 高 | 低 | 极低 | 高 |
| 社区成熟度 | 高 | 高 | 中 | 低 | 高(国内) |
8.2 架构定位对比
┌─────────────────────────────────────────────────────────────┐
│ 业务用户 / BI 工具 / 数据应用 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ 维度建模 │ │ 信息集市 │ │ ADS 宽表 │ │ 图查询 │ │
│ │(Data Mart)│ │(Info Mart)│ │ (OneData) │ │(Graph DB) │ │
│ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │
│ │ │ │ │ │
│ ┌─────┴──────────────┴─────────────┴──────────────┘ │
│ │ │
│ ┌┴────────────────────────────────────────────────────┐ │
│ │ 企业级数据仓库(EDW) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │ │
│ │ │ 3NF 模型 │ │Data Vault│ │ Anchor │ │OneData │ │ │
│ │ │(Inmon) │ │ 模型 │ │ 模型 │ │ DWD/DWS│ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
├─────────────────────────────────────────────────────────────┤
│ 源系统(OLTP / IoT / 日志) │
└─────────────────────────────────────────────────────────────┘
8.3 选型决策树
开始
│
├─ 是否需要完整审计追踪?
│ ├─ 是 → 是否多源系统集成?
│ │ ├─ 是 → 属性变更频率差异是否极大?
│ │ │ ├─ 是 → Anchor Modeling
│ │ │ └─ 否 → Data Vault
│ │ └─ 否 → 3NF + 审计字段
│ │
│ └─ 否 → 是否面向业务分析查询?
│ ├─ 是 → 是否需要指标治理?
│ │ ├─ 是 → OneData 方法论
│ │ └─ 否 → 维度建模
│ └─ 否 → 是否作为企业单一数据源?
│ ├─ 是 → 3NF
│ └─ 否 → 维度建模(快速交付)
九、现代数据湖仓中的建模实践
9.1 分层建模架构
在现代湖仓架构中,多种建模方法协同使用:
┌─────────────────────────────────────────────────────┐
│ Serving 层 / Semantic 层 │
│ ┌─────────────────────────────────────────────┐ │
│ │ 维度建模 / OBT 宽表 / 图查询 │ │
│ │ - 面向业务的主题域星型模型 │ │
│ │ - 宽表 / 汇总表 / 指标矩阵 │ │
│ │ - 直接服务 BI 和数据应用 │ │
│ └─────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────┤
│ Common / Integration 层 │
│ ┌─────────────────────────────────────────────┐ │
│ │ Data Vault / 3NF / OneData DWD+DWS │ │
│ │ - 企业级数据集成与治理 │ │
│ │ - 统一业务键、一致性维度 │ │
│ │ - 完整历史追踪与审计 │ │
│ └─────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────┤
│ Raw / Bronze 层 │
│ ┌─────────────────────────────────────────────┐ │
│ │ 贴源层:保持源系统结构,只追加 │ │
│ │ - CDC / 全量同步 │ │
│ │ - 不做任何业务逻辑转换 │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
9.2 湖仓场景下的建模建议
| 湖仓分层 | 推荐建模方式 | 说明 |
|---|---|---|
| Bronze / Raw | 贴源(1:1 映射) | 保持源系统结构,不做转换 |
| Silver / Integration | Data Vault 或 3NF 或 OneData DWD | 数据集成、清洗、去重,保留历史 |
| Gold / Serving | 维度建模 / OBT 宽表 | 星型模型、宽表,面向查询优化 |
9.3 代码示例:在湖仓中实现 Data Vault
以下以 Apache Iceberg + Spark 为例,演示 Data Vault 的基本实现:
Hub 表加载(仅插入新业务键):
sql
INSERT INTO hub_customer
SELECT
SHA1(CONCAT_WS('||', src.customer_id)) AS hk_customer,
src.customer_id AS bk_customer_id,
CURRENT_TIMESTAMP() AS load_date,
'erp_customer' AS record_source
FROM source_customers src
LEFT JOIN hub_customer hub
ON src.customer_id = hub.bk_customer_id
WHERE hub.bk_customer_id IS NULL;
Satellite 表加载(Hash Diff 变更检测):
sql
INSERT INTO sat_customer_details
SELECT
hub.hk_customer,
CURRENT_TIMESTAMP() AS load_date,
'erp_customer' AS record_source,
src.customer_name,
src.customer_email,
src.customer_phone,
src.city,
SHA1(CONCAT_WS('||',
COALESCE(src.customer_name, ''),
COALESCE(src.customer_email, ''),
COALESCE(src.customer_phone, ''),
COALESCE(src.city, '')
)) AS hash_diff
FROM source_customers src
INNER JOIN hub_customer hub
ON src.customer_id = hub.bk_customer_id
LEFT JOIN (
SELECT hk_customer, hash_diff,
ROW_NUMBER() OVER (PARTITION BY hk_customer ORDER BY load_date DESC) AS rn
FROM sat_customer_details
) cur ON hub.hk_customer = cur.hk_customer AND cur.rn = 1
WHERE cur.hk_customer IS NULL
OR SHA1(CONCAT_WS('||',
COALESCE(src.customer_name, ''),
COALESCE(src.customer_email, ''),
COALESCE(src.customer_phone, ''),
COALESCE(src.city, '')
)) != cur.hash_diff;
从 Data Vault 构建维度模型(信息集市):
sql
CREATE TABLE dim_customer AS
SELECT
hub.hk_customer,
hub.bk_customer_id AS customer_id,
sat_name.customer_name,
sat_contact.customer_email,
sat_contact.customer_phone,
sat_contact.city,
sat_name.load_date AS name_valid_from,
sat_name.load_end_date AS name_valid_to
FROM hub_customer hub
LEFT JOIN (
SELECT hk_customer, customer_name, load_date, load_end_date,
ROW_NUMBER() OVER (PARTITION BY hk_customer ORDER BY load_date DESC) AS rn
FROM sat_customer_name
) sat_name ON hub.hk_customer = sat_name.hk_customer AND sat_name.rn = 1
LEFT JOIN (
SELECT hk_customer, customer_email, customer_phone, city,
ROW_NUMBER() OVER (PARTITION BY hk_customer ORDER BY load_date DESC) AS rn
FROM sat_customer_details
) sat_contact ON hub.hk_customer = sat_contact.hk_customer AND sat_contact.rn = 1;
十、总结与选型建议
10.1 核心原则
没有"最好的"建模方法,只有"最适合"的。选择取决于业务需求、团队能力、技术架构和组织规模。
10.2 选型速查表
| 你的场景 | 推荐方法 | 原因 |
|---|---|---|
| 快速构建 BI 报表 | 维度建模 | 直观、高效、迭代快 |
| 企业级数据整合 | Data Vault | 可扩展、可审计、多源集成 |
| 监管合规要求 | Data Vault 或 3NF | 完整历史追踪 |
| 数据湖仓中间层 | Data Vault | 与贴源层衔接好,保留历史 |
| 数据湖仓服务层 | 维度建模 | 查询性能优,BI 友好 |
| 主数据管理 | 3NF | 数据一致性保证 |
| 实时指标看板 | OBT(宽表) | 无 JOIN,查询极快 |
| 用户行为分析 | 维度建模 / Activity Schema | 事件驱动,漏斗分析 |
| 指标口径治理 | OneData | 统一指标体系,规范治理 |
| 国内互联网数仓 | OneData | 生态成熟,人才储备丰富 |
| 风控关系网络 | 图建模 | 多跳遍历,关系发现 |
| IoT 设备监控 | 时序建模 | 高吞吐写入,降采样 |
| 属性独立演进 | Anchor Modeling | 极致规范化,零耦合 |
| 多领域自治 | Data Mesh + 领域建模 | 去中心化,领域自治 |
10.3 混合架构建议
在大多数企业实践中,混合架构是最常见也最务实的选择:
- Raw 层:贴源同步,1:1 映射
- Integration 层:Data Vault 或 3NF 或 OneData DWD/DWS,确保数据集成与历史留存
- Serving 层:维度建模或宽表,面向业务查询优化
这种分层架构让每一层各司其职:Raw 层保证数据不丢失,Integration 层保证数据可追溯,Serving 层保证数据好用。三层之间通过 ETL/ELT 管道衔接,形成从源系统到业务决策的完整数据价值链。
10.4 方法论演进趋势
| 趋势 | 说明 |
|---|---|
| 方法论融合 | Data Vault + 维度建模的混合架构成为主流,Integration 层用 DV,Serving 层用维度建模 |
| 实时化 | OneData 等方法论正在从离线扩展到实时,Kappa 架构下的流式建模成为新课题 |
| 声明式建模 | dbt 等工具推动"建模即代码",声明式 SQL 替代手动 ETL |
| 语义层兴起 | Cube、Metrics Layer 等语义层技术将指标定义从模型中解耦 |
| AI 辅助建模 | LLM 正在尝试自动生成 E-R 图、推荐维度模型、检测指标口径冲突 |
更多信息请参考以下经典著作与资源:
- Ralph Kimball 等,《The Data Warehouse Toolkit》
- Bill Inmon,《Building the Data Warehouse》
- Dan Linstedt & Michael Olschimke,《Building a Scalable Data Warehouse with Data Vault 2.0》
- Lars Rönnbäck,《Anchor Modeling》学术论文
- Zhamak Dehghani,《Data Mesh》
- 阿里巴巴,《OneData 数据建设规范》