一、什么是数据建模
**数据建模:**就是将现实世界中复杂、无序的业务数据,通过一套标准化的流程(概念→逻辑→物理)和科学的方法论(如关系模型、维度模型),转化为结构化、高内聚、低冗余、易使用的数据资产的过程。
数据建模的核心三要素:
- 定义"有什么":识别出所有业务相关的核心对象,比如"客户"、"产品"、"订单"、"交易"。
- 定义"什么特征":明确每个对象的具体属性。例如"客户"有"姓名"、"电话"、"注册日期"。
- 定义"什么关系":说明不同对象之间的联系。例如一个"客户"可以下多个"订单";一个"订单"包含多个"产品"。
二、 数据建模的三个阶段:概念、逻辑、物理模型
这是从业务需求到最终物理实现的渐进过程,是数据建模实践的三个标准阶段。它们构成了一个从抽象到具体、从业务到技术的完整工作流:
-
概念模型
-
核心:与业务人员沟通,画出"业务草图",只关注核心业务实体和它们之间的关系,不涉及任何技术细节。 即定义"有什么","什么关系"。
-
产出物:实体关系图(ER图,即Entity-Relationship Diagram的缩写,描述实体及其关系的图形化工具),只有实体和关系,没有属性或主键。
-
-
逻辑模型
-
核心:在概念模型基础上,将草图细化为"详细设计图"。详细定义每个实体的具体属性(字段)、数据类型、主键、外键等,但不管数据库技术。即定义"什么特征"。在这个阶段,你可以选择采用关系模型、维度模型等作为你的设计蓝图。
-
产出物:详细的ER图或表结构定义(字段名、类型、主外键关系)。
-
-
物理模型
-
核心:在逻辑模型基础上,针对具体使用的数据库和硬件环境,进行最优化设计。即定义"怎么存"。
-
**产出物:**如分区策略(按日期分区)、分桶、索引、压缩方式、存储格式(Parquet/ORC)、数据生命周期等。
-

三、逻辑建模的几种主流方法
| 模型 | 核心思想 | 典型结构 | 适用场景 | 代表领域 |
|---|---|---|---|---|
| 关系模型 | 基于数学集合论,通过外键关联,遵循范式(通常3NF)消除冗余 | 大量规范化的小表,像一张网 | OLTP(在线事务处理),如银行交易、电商订单等高频增删改业务。 | MySQL, PostgreSQL, Oracle |
| 维度模型 | 分为事实表(可度量数值)和维度表(描述事实的文本),反范式化,便于分析 | 星型模型、雪花模型、星座模型 | OLAP(在线分析处理),如数据仓库、BI 报表、商业智能分析 | Hive, ClickHouse, Doris, Tableau |
| Data Vault模型 | 混合范式,强调历史追溯和可扩展性。由中心表(Hub)、链接表(Link)、附属表(Satellite)组成 | 类似分布式系统的图谱 | 企业级数据仓库(EDW),需要完整历史变化、适应源系统频繁变更 | 大型金融、电信企业数仓 |
四、关系模型
关系模型由E.F. Codd于1970年提出,是主流关系型数据库(MySQL、PostgreSQL、Oracle等)的理论基础。其核心思想是:将所有数据基于实体和关系,表示为二维表,表与表之间通过外键关联,并严格遵守范式(通常到第三范式),确保数据无重复、无歧义。
| 术语 | 通俗解释 | 例子(学生表) |
|---|---|---|
| 关系 | 一张二维表 | Student 表 |
| 元组 | 表中的一行 | 一条学生记录 |
| 属性 | 表中的一列 | 学号, 姓名, 班级 |
| 域 | 属性的取值范围 | 性别 域:{'男', '女'} |
| 候选键 | 能唯一标识一行的一个或多个属性 | 学号(每个学生唯一) |
| 主键 | 选定的一个候选键 | 学号 |
| 外键 | 一个表中的属性,引用另一个表的主键 | 选课表中的学号引用学生表的学号 |
**三范式:**是规范化过程的核心标准,目的是消除数据冗余、避免插入、更新、删除异常。从第一范式到第三范式,要求逐渐严格。注意:还有BCNF(巴斯-科德范式,是3NF的改进)、第四、第五范式等,但实际工程中通常满足3NF就足够了。
1. 第一范式(1NF):所有字段原子
定义 :关系中的每个属性都必须是不可再分的原子值,不允许表中套表(或集合、数组等复合结构)。
-
解决的问题:保证字段的原子性,使每个字段只存储单一值。
-
违规示例:
| 学号 | 姓名 | 所选课程 |
|---|---|---|
| 001 | 张三 | 数学, 英语 |
| 002 | 李四 | 语文 |
这里"所选课程"列存储了多个课程(用逗号分隔),不是原子值。
- 符合1NF的改造:拆成多行,每行一个课程。
| 学号 | 姓名 | 课程 |
|---|---|---|
| 001 | 张三 | 数学 |
| 001 | 张三 | 英语 |
| 002 | 李四 | 语文 |
2. 第二范式(2NF):所有非主属性完全依赖于整个候选键
定义 :满足1NF,且不存在部分函数依赖。即:所有非主属性必须完全依赖于整个候选键(而不是候选键的一部分)。
-
解决的问题:消除"部分依赖"导致的冗余和异常(常见于联合主键表)。
-
违规示例 :学生选课成绩表,联合主键为
(学号, 课程号)。
| 学号 | 课程号 | 课程名称 | 成绩 |
|---|---|---|---|
| 001 | C01 | 数学 | 90 |
| 001 | C02 | 英语 | 85 |
| 002 | C01 | 数学 | 92 |
这里候选键是 (学号, 课程号),但 课程名称 只依赖于 课程号 ,而不依赖于 学号 → 这就是部分函数依赖。存在的问题:
-
冗余:数学课程名称在每个选该课的学生记录中都重复存储。
-
更新异常:若把"数学"改成"高等数学",需要更新多行。
-
删除异常:若某课程只有一名学生且该生退课,课程信息会丢失。
-
符合2NF的改造:将表拆分为两个表。
-
选课表 :
(学号, 课程号, 成绩),主键(学号, 课程号)。 -
课程表 :
(课程号, 课程名称),主键课程号。
-
3. 第三范式(3NF):每个非主属性直接依赖于主键,无传递依赖
定义 :满足2NF,且不存在传递函数依赖。即:非主属性不能依赖于其他非主属性(必须直接依赖于主键)。
-
解决的问题:消除"传递依赖"导致的冗余和异常。
-
违规示例 :学生表如下,主键为
学号。
| 学号 | 姓名 | 班级编号 | 班级名称 | 班主任 |
|---|---|---|---|---|
| 001 | 张三 | B01 | 计算机1班 | 王老师 |
| 002 | 李四 | B01 | 计算机1班 | 王老师 |
| 003 | 王五 | B02 | 计算机2班 | 李老师 |
这里 学号 → 班级编号 → 班级名称, 班主任。非主属性 班级名称 和 班主任 依赖于 班级编号,而 班级编号 依赖于 学号 → 传递依赖。存在的问题:
-
冗余:班级信息重复存储(每个学生都存一遍班级名称、班主任)。
-
更新异常:若计算机1班班主任换成张老师,需要更新所有该班学生的记录。
-
符合3NF的改造:拆分为两个表。
-
学生表 :
(学号, 姓名, 班级编号),主键学号,外键班级编号引用班级表。 -
班级表 :
(班级编号, 班级名称, 班主任),主键班级编号。
-
4. 三范式总结
| 范式 | 核心要求 | 违规特征 | 解决方法 |
|---|---|---|---|
| 1NF | 列不可再分 | 某列包含多个值(逗号列表、数组) | 拆分为多行,或拆分新表 |
| 2NF | 消除部分依赖 | 联合主键下,某列只依赖部分主键 | 拆分出依赖该部分主键的新表 |
| 3NF | 消除传递依赖 | 非主键列依赖于其他非主键列 | 拆分出依赖的非主键列作为新表主键 |
五、维度模型
维度模型是数据仓库大师 Ralph Kimball 提出的一种面向分析的逻辑模型。其核心思想是:将数据组织成"事实"和"维度"两部分,通过星型或雪花型结构,提供高性能、易理解的查询体验。
1. 事实表(Fact Table)
事实表存储业务过程的**可度量的事件或指标(如销售额、数量、金额),以及关联维度表的外键。**每一行对应一个业务事件或一个度量快照。
- 事实表的类型(按粒度划分)
| 类型 | 说明 | 示例 | 示例字段 |
|---|---|---|---|
| 事务事实表 | 记录每个业务事务/事件的一行。它是粒度最细、最原子化的事实表,通常反映一个可度量的业务操作,如一次订单下单,一次交易。 | 电商订单事务表:记录每笔订单中每个商品的销售明细 | 订单ID、商品ID、单价、数量、金额、时间戳。 |
| 周期快照事实表 | 在固定时间间隔(如每天、每月)对某个业务状态进行快照,它记录的是某个时间点的度量值,而不是事务的发生过程。常用于累积度量(如账户余额、库存量)。 | 每日库存快照表:记录每个仓库中每个商品在每天结束时的库存量。 | 日期、仓库ID、商品ID、库存量。 |
| 累积快照事实表 | 记录一个完整业务流程从开始到结束的各个里程碑(如订单的创建、支付、发货、完成),通常有多个时间外键。 | 订单生命周期表:每个订单一行,记录从创建到完成的关键时间点。如待支付、已支付、已发货等。 | 订单ID、创建日期、支付日期、发货日期、订单金额、状态。 |
| 无事实的事实表 | 是一种特殊的事实表,它没有数值度量,只包含维度的外键组合,用于记录事件是否发生。每一行代表一个事实:某个组合的维度在某个时间点存在。 | 学生考勤表:记录某天某学生是否出勤。 | 日期、学生ID、课程ID、出勤标志 (可省略) |
-
事务明细 → 事务事实表。
-
周期性状态 → 周期快照事实表。
-
业务流程跟踪 → 累积快照事实表。
-
仅记录存在性 → 无事实事实表。
-
事实表的实现方式
| 类型 | 数据来源 | 要点 |
| 事务事实表 | 来源于业务系统的事务表(ODS层),通常是按时间戳增量抽取 | * 加载方式:追加,不做历史更新。 * 分区策略:按业务日期(如 dt 字段)分区,提升查询性能。 |
| 周期快照事实表 | * 方式一:基于事务事实表聚合(如计算每月的交易情况汇总)。 * 方式二:直接从源系统的状态表抽取(如每日末的账户余额表)。 | 通常需要全量或增量计算(可维护 前一日快照 + 当日增量 的方式(拉链思想))。 |
| 累积快照事实表 | 事务事实表或业务流程日志(如订单的创建、支付、发货等事件)。需要能够跟踪同一业务流程实例的多个里程碑状态。 | 每当流程推进到新里程碑时,更新该行的对应里程碑日期字段和状态字段。 |
| 无事实的事实表 | * 来源A:维度组合的"覆盖关系"。例如学生选课:学生维度 × 课程维度,但只保留实际选课的组合。 * 来源B:事件日志中仅记录"发生"而无数值的事件(如页面浏览,无金额)。 | * 没有度量列,或仅有一个常量列(如 dummy = 1)以方便计数。 * 加载方式:追加(事件型)或 全量覆盖(关系型)。 |
|---|
2. 维度表(Dimension Table)
维度表是存储描述性信息的表,用于解释事实表记录的业务属性 。
- 缓慢变化维(Slowly Changing Dimensions, SCD)