DDIA 1-3-1 关系模型与文档模型
关系模型与文档模型:核心概念、差异与应用场景详解
在现代数据密集型应用中,关系模型与文档模型是最常被讨论的两大数据建模方式。两者分别代表了“以结构化表格组织数据”与“以自包含文档存储数据”两种思想体系。理解它们的优劣、适用场景以及设计权衡,是系统设计与数据库选型中的基础能力。
本文从概念、结构特征、典型使用方式、性能特征,到模式灵活性与查询语言支持等方面,对两大模型进行系统梳理。
一、关系模型(Relational Model)
1. 基本概念
关系模型由 Edgar Codd 于 1970 年提出,是所有关系型数据库(如 MySQL、PostgreSQL、Oracle)的理论基石。
核心概念包括:
- 关系(Relation):在 SQL 中对应 表(Table)
- 元组(Tuple):对应 行(Row)
- 属性(Attribute):对应 列(Column)
- 主键(Primary Key)/外键(Foreign Key):用于标识对象与对象之间的关联
- 连接(Join):通过键将数据组合起来,是关系系统强大的关键
典型结构示意(如“用户—职位”结构):
users(id, first_name, last_name, region_id ...)
positions(id, user_id, job_title, organization ...)
education(id, user_id, school_name, start, end)
适合表达 复杂关系、规范化、多对多、多对一 结构的数据。
2. 关系模型的优势
(1)强关系表达能力
- 多对一、多对多、一对多都可以使用关联表表达
- 连接查询天然支持复杂数据关系分析
(2)成熟的查询语言(SQL)
声明式查询语言能让开发者专注于“要什么”,无需指定“怎么做”。
(3)模式固定,保证数据一致性
写入前就保证结构正确,适合数据高度结构化的业务,如
- 金融
- 企业管理系统(ERP、CRM)
- 电商订单系统
3. 关系模型的局限
(1)对象关系阻抗不匹配(ORM问题)
应用代码使用对象(树结构),数据库使用表(扁平结构),需要大量转换。
例如复杂对象存储需要拆分成多张表,导致:
- 模式冗长
- 必须做多表 join
- ORM 框架常出现性能问题(如 N+1 查询)
(2)读取一整个对象成本高
如用户简历含多个职位、教育经历,需要多表 join,延迟明显。
二、文档模型(Document Model)
文档模型常用 JSON(或 BSON)表示整个对象,自包含结构,广泛用于 MongoDB、Couchbase,以及 PostgreSQL 的 JSONB 列。
示例:
{
"user_id": 251,
"first_name": "Barack",
"positions": [
{"job_title": "President", "organization": "USA"},
{"job_title": "Senator", "organization": "US Senate"}
],
"education": [...],
"contact_info": {...}
}
适合表达 树形、一对少(One-to-few) 的数据结构。
1. 文档模型的优势
(1)天然匹配对象结构
应用层对象往往是嵌套结构,文档模型直接使用 JSON 存储:
- 减少 ORM 复杂度
- 读取简单对象结构无需 join
(2)优秀的局部性(Locality)
相关数据存放在一个文档里,一次查询即可拿到全部内容。
适合:
- 用户档案
- 订单及其行项目
- 网站内容(文章、评论结构较少时)
(3)模式灵活(Schema-on-read)
文档可以随时添加字段,而不会影响旧文档。
适应快速变化的业务需求。
2. 文档模型的局限
(1)不擅长多对多、多对一关系
嵌套结构只能表达树,而实际业务常是图或网状结构。
需要引用(Reference)方式或额外反规范化。
(2)文档过大或更新频繁,会带来性能问题
文档通常以整体存取,更新一个字段可能需要重写整个文档。
三、规范化与反规范化(Normalization vs Denormalization)
关系模型强调规范化,文档模型倾向反规范化。
1. 规范化(Normalization)
目标:减少重复数据,提升一致性
优点:
- 写入成本更低(更新只需改一处)
- 消除一致性风险
缺点:
- 查询成本更高,需要 join
- 复杂结构查询变慢
2. 反规范化(Denormalization)
目标:加速读取
优点:
- 读取更快(减少 join)
- 查询逻辑更简单
缺点:
- 写入成本更高(需同步多个副本)
- 存储更大
- 数据一致性风险
文档模型通常采用反规范化,关系模型常采用规范化。
四、关系模型 vs 文档模型:概念上的根本差异
| 维度 | 关系模型 | 文档模型 |
|---|---|---|
| 数据结构 | 表(二维) | JSON 文档(多层树结构) |
| 关系表达 | 强,支持一对多、多对多 | 弱,只适合树结构 |
| 查询 | SQL,强大连接能力 | 文档查询/聚合管道 |
| 局部性 | 差,需 join | 强,整个文档一次 IO |
| 模式 | 写时模式(Schema-on-write) | 读时模式(Schema-on-read) |
| 更新成本 | 低,按行更新 | 高,可能重写整个文档 |
| 最适场景 | 分析型、事务型、高度结构化业务 | 内容系统、用户档案、嵌套数据 |
五、何时选择关系模型?
关系模型适合:
✓ 数据关系复杂
多对多、多对一、关联查询多且深:
- 社交关系(部分场景)
- 商品库存 & 供应链
- 交易系统
✓ 数据高度结构化
模式固定不变。
✓ 需要强一致性、约束
如:唯一索引、外键、事务 ACID。
✓ OLAP/分析系统
星型/雪花模型天然属于关系模型。
六、何时选择文档模型?
文档模型适合:
✓ 数据天然是树形结构
典型结构是“一对少”,例如:
- 简历(用户 -> 职位/教育)
- 电商订单(订单 -> 订单项)
- 文章(文章 -> 标签/附件)
✓ 需要模式灵活
字段不断增加/变化。
✓ 想要更快读取整个对象
减少 join,改善 IO 局部性。
✓ 不需要复杂的关系查询
如果数据不需要 join 或 join 不频繁,文档优异。
七、两者的融合趋势
现代数据库逐渐融合两者特性:
关系数据库 → 加入文档特性
- PostgreSQL JSONB
- MySQL JSON
- Oracle JSON
- 支持文档索引、半结构化查询
文档数据库 → 加入关系特性
- MongoDB $lookup(类似 join)
- Couchbase N1QL 类 SQL 查询
- 二级索引支持越来越成熟
最终形态趋向:
关系 + 文档混合模式;业务按需选择最佳模型结构。
八、总结:选型核心思考框架
可使用如下简单决策树:
是否存在大量多对多关系?
➡ 是:关系模型
数据是否天然是树(JSON-like)结构?
➡ 是:文档模型
读取是否以整个对象为主?(高局部性)
➡ 是:文档模型
是否需要统一结构(写时模式)?
➡ 是:关系模型
写入是否比读取更多且需保持一致?
➡ 是:关系模型(规范化更安全)
业务结构是否变化快?
➡ 是:文档模型(模式灵活)