什么是第三范式(3NF)?
概念背景
第三范式(Third Normal Form, 3NF)源于关系型数据库理论,由 E.F. Codd 提出,也是传统 OLTP(在线事务处理)系统(如 ERP、CRM)的标准设计方法。Inmon 学派主张在数据仓库中也采用 3NF 构建企业级数据仓库(EDW)。
核心原则
要满足 3NF,表结构必须依次满足以下三个条件:
- 第一范式(1NF):列不可再分(原子性)。
- 第二范式(2NF):非主键列完全依赖于主键(消除部分依赖)。
- 第三范式(3NF):非主键列直接依赖于主键,不存在传递依赖(即:非主键列之间不能相互依赖)。
通俗理解:3NF 的核心目标是消除冗余,确保“一事一地”。每个事实只存储一次,通过外键关联来还原完整信息。
3NF 实例说明:电商订单系统
假设我们要存储“订单”、“用户”和“商品”的信息。
如果不遵循 3NF(存在冗余和传递依赖):
订单ID |
用户ID |
用户名 |
用户所在省份 |
商品ID |
商品名称 |
商品类别 |
数量 |
金额 |
1001 |
U01 |
张三 |
广东 |
P01 |
iPhone |
手机 |
1 |
5999 |
1002 |
U01 |
张三 |
广东 |
P02 |
耳机 |
配件 |
2 |
299 |
问题:如果张三改了名字,或者“广东”改为“广东省”,需要修改多行数据;如果删除了所有订单,张三的信息也就丢失了。
遵循 3NF 的设计(拆分为多个表):
表 A:用户表 (Users) - 存储用户属性
用户ID (PK) |
用户名 |
所在省份 |
U01 |
张三 |
广东 |
表 B:商品表 (Products) - 存储商品属性
商品ID (PK) |
商品名称 |
商品类别 |
P01 |
iPhone |
手机 |
P02 |
耳机 |
配件 |
表 C:订单事实表 (Orders) - 仅存储交易过程和关联键
订单ID (PK) |
用户ID (FK) |
商品ID (FK) |
数量 |
金额 |
下单时间 |
1001 |
U01 |
P01 |
1 |
5999 |
2026-03-01 |
1002 |
U01 |
P02 |
2 |
299 |
2026-03-02 |
优点:数据极度规范,无冗余,更新维护成本低(改用户名只需改一行),数据一致性高。
缺点:查询时需要大量的 JOIN 操作(订单表 JOIN 用户表 JOIN 商品表),对于海量数据分析,性能较差。
什么是维度模型(Dimensional Modeling)?
概念背景
维度模型由 Ralph Kimball 提出,专为 OLAP(在线分析处理)和数据仓库设计。它的核心目标不是消除冗余,而是优化查询性能和提升业务可读性。
核心结构:星型模型(Star Schema)
维度模型通常由两类表组成:
- 事实表(Fact Table):位于中心,存储业务过程的度量值(如金额、数量)和外键。通常是窄而深的表。
- 维度表(Dimension Table):围绕在事实表周围,存储描述性的文本属性(如谁、什么、哪里、何时)。通常是宽而浅的表。
核心原则:反规范化(Denormalization)。为了减少 JOIN,允许维度表中存在冗余数据,甚至将层级结构(如 省->市->区)扁平化放在一张表中。
维度模型实例说明:电商销售分析
我们将上述 3NF 的例子转化为维度模型(星型模型):
事实表:销售事实表
销售ID |
日期Key |
用户Key |
商品Key |
销售金额 |
销售数量 |
1 |
20260301 |
101 |
501 |
5999 |
1 |
2 |
20260302 |
101 |
502 |
598 |
2 |
维度表:用户维度表- 包含冗余和层级
用户Key (PK) |
用户ID |
用户名 |
性别 |
年龄段 |
省份 |
城市 |
会员等级 |
注册日期 |
101 |
U01 |
张三 |
男 |
25-30 |
广东 |
深圳 |
黄金 |
2025-01-01 |
维度表:商品维度表
商品Key (PK) |
商品ID |
商品名称 |
一级类目 |
二级类目 |
品牌 |
单价 |
501 |
P01 |
iPhone |
数码 |
手机 |
Apple |
5999 |
502 |
P02 |
耳机 |
数码 |
配件 |
Apple |
299 |
维度表:日期维度表
日期Key (PK) |
完整日期 |
年 |
季 |
月 |
日 |
是否周末 |
是否节假日 |
20260301 |
2026-03-01 |
2026 |
Q1 |
3 |
1 |
否 |
否 |
20260302 |
2026-03-02 |
2026 |
Q1 |
3 |
2 |
是 |
否 |
优点:
- 查询极快:大部分查询只需要
FactJOINDim一次,甚至不需要 JOIN(如果指标都在事实表)。 - 业务易懂:业务人员看到
Dim_User就能理解“广东深圳的黄金会员张三”,无需理解复杂的表关联逻辑。 - 支持切片/切块:非常适合按时间、地区、类别进行多维分析。
缺点:
- 数据冗余大(例如“广东”在用户表中重复存储了多次)。
- 数据更新复杂(如果“广东”改名为“粤”,需要更新大量行,通常使用缓慢变化维 SCD 技术处理)。
维度模型 vs 第三范式(3NF)对比
特性 |
第三范式 (3NF / Inmon) |
维度模型 (Kimball) |
核心目标 |
数据一致性、消除冗余、灵活适应未知查询 |
查询性能、业务易理解性、快速交付 |
数据结构 |
高度规范化,表多且细,关系复杂(雪花状或网状) |
反规范化,表少且宽,结构简单(星型) |
冗余度 |
极低(几乎无冗余) |
高(故意保留冗余以减少 JOIN) |
查询性能 |
低。分析查询需要大量 JOIN,计算成本高 |
高。JOIN 少,聚合速度快,适合 BI 工具直连 |
业务友好度 |
低。业务人员难以理解复杂的表关联逻辑 |
高。直观映射业务流程,业务术语清晰 |
数据更新 |
容易。修改一处即可同步全局 |
困难。需处理缓慢变化维(SCD),批量更新成本高 |
总结建议
存数据用 3NF(省空间、保一致),查数据用维度模型(跑得快、好理解)。