ER建模

从ER建模到关系规范化:数据库设计的完整流程

Posted by CloudingYu on March 24, 2026

本文知识点

  • 数据库设计生命周期:从规划、需求分析到物理设计与运行维护的完整流程
  • ER 模型基础:实体、属性类型、联系的度与基数
  • ER 图设计:局部ER图设计、全局ER图合并、冲突检查、ER图转关系模式
  • ER 模型扩展:弱实体、继承层次与存储策略、知识图谱与图数据库
  • 关系规范化引论:数据依赖、范式、冗余异常与模式分解

一、数据库设计生命周期

1.1 数据库设计概述

数据库与软件密不可分,数据库工程可以视为软件工程的一部分。一个数据库系统同样经历从规划、设计、实现到运行维护的完整生命周期。

数据库设计的输入是各种需求(业务需求、信息需求),经过概念设计、逻辑设计、物理设计,最终实现和运行维护。这三个层次对应数据库的三级模式结构。

1.2 规划阶段

规划阶段需要明确:

  • 系统目标:数据库上面要支撑哪些信息系统、哪些功能
  • 系统调查:对整个企业组织进行调查,了解企业内部有哪些数据以及数据之间的逻辑关系

企业信息系统的数据库设计需要具备前瞻性。一套数据库建好后可能支撑几十上百个微服务,且新应用还在持续开发中。数据库只有一套,但上层应用可能不断增长,因此设计阶段就必须考虑未来的扩展需求。

  • 多角度评估
    • 技术角度:并发性、用户规模。少量用户(十几人)选集中式数据库即可;几百人需要分布式数据库;上万人可能需要 NoSQL 或 NewSQL
    • 经济角度:国产数据库 vs 商业数据库,集中式 vs 分布式,价格差异很大
    • 法律角度:隐私合规、安全合规,特别是医疗、政府、军队系统

案例(上海图书馆):上图从最初只管理老馆读者(每天几百人),扩展到统一管理全上海所有社区图书馆(上万人以上),系统的选型和设计需要随之调整。此外上图除图书外还管理大量文献(民国报纸、图片等),涉及图片存储时需考虑 NoSQL 数据库。

1.3 需求分析阶段

需求分析的目标是将业务流程梳理清楚:

  1. 梳理业务流程图:画出业务的实施过程,了解有哪些业务流程
  2. 设计数据流图(DFD):从业务流程中找出涉及哪些数据,标记数据处理过程
  3. 产生数据字典:定义清楚所有数据项

需求分析不要求像软件需求那样精确描述功能细节,但必须把业务流程和数据梳理清楚。

1.4 概念设计阶段

概念设计的目标是明确数据——有哪些数据、用什么字段来描述这些数据。

概念设计分两步:

  1. 局部 ER 图:围绕不同的用户(或不同的应用),分别设计局部 ER 图
  2. 全局 ER 图:将局部 ER 图合并成一张完整的 ER 图

1.5 逻辑设计阶段

将概念设计(ER 图)转化为数据库的关系表结构。

  • ER 图可以直接转换得到关系模式,但这个模式可能不够好(存在冗余)
  • 需要不断对模式进行优化和修正,去除冗余
  • 去除冗余会导致表被拆分,进而导致查询时需要更多的连接操作(JOIN),而连接的性能较差
  • 因此需要在去除冗余(数据质量)查询性能之间做权衡

规范化设计(第四章)的核心问题是:评价 ER 图转换得到的关系模式是否足够好,并消除其中的冗余。

1.6 物理设计阶段

决定数据怎么存——数据存放在硬盘上的具体方式:

  • 表存放在哪块硬盘上(多块硬盘的情况下)
  • 日志存放在哪(旧硬盘 vs 新硬盘的选择)
  • 索引结构的设计(如何加速查询)
  • 用户权限设置
  • 安全性考虑

1.7 实现与运行维护

  • 数据迁移:从老系统迁移到新系统
  • 功能测试与性能测试:测试不同并发情况下的性能、每个查询的执行时间
  • 日常维护:每天备份、安全性和完整性控制、性能监控
  • 分库分表:随着数据积累,按年/按月将数据拆分,保证每张表不至于太大

例如,银行交易系统通常要求每次交易的响应时间不超过 3 秒。


二、ER 模型(实体联系模型)

2.1 ER 模型的发展历史

ER 模型(Entity-Relationship Model)伴随着关系数据库的诞生而出现,主要用于描述:

  • 实体(Entity)
  • 实体之间的联系(Relationship)
  • 实体的属性(Attribute)

在关系数据库相对成熟之后,对 ER 模型的研究一度减少。但近年来,随着大数据图数据库的兴起,基于 ER 模型的图数据结构再次受到关注。

大数据时代数据碎片化严重,而实体-关系这种描述方式非常灵活,催生了图数据库的发展。图数据库的结构和 ER 图非常相似。

2.2 属性的类型

属性类型 说明 示例
单值属性 只有一个值 姓名、性别
多值属性 可以取多个值 销售价格(代销价、批发价、零售价、优惠价等)
复合属性 具有层次结构的属性 地址(邮政编码、省、市、区、街道、门牌号)
派生属性 可以从其他属性计算得出 实发工资 = 基本工资 + 奖金 - 房租

设计技巧:对于多值属性(如销售价格),如果把所有价格类型都作为列放在一张表里,新增一种价格就要加一列,非常不灵活。更好的做法是把”销售价格”单独作为一个实体,包含”销售方式”和”具体价格”两个属性,然后用关联来连接。

设计技巧:对于派生属性(如实发工资),不需要一定要存放在数据库里,因为它可以从其他属性计算出来,存了反而是冗余。

2.3 联系的度(Degree)

联系按参与的实体数量分为:

说明 示例
一元联系 联系只涉及一个实体 运动员的名次顺序(前一名、后一名都是运动员)
二元联系 联系涉及两个实体 教师教学生、零件由子零件组成
三元联系 联系涉及三个实体 进货(从商店买商品放入仓库)

2.4 联系的基数(Cardinality)

基数类型 说明 示例
一对一(1:1) 每个实体最多与对方一个实体关联 运动员的成绩排名顺序
一对多(1:N) 一方对应多方 领导与职工(一个领导管多个职工)
多对多(M:N) 双方都是多对多 零件组成(一个零件由多个子零件构成,一个子零件参与多个零件)

联系还可以加基数限制,例如:每个学生选课 1-6 门,每门课不超过 50 个学生。

2.5 设计中的实用技巧

分离常变属性与不变属性

对一个实体,常变的属性(如职务、工资、奖金)和不变的属性(如姓名、出生日期)可以分开存储。

这样做的原因有两个:一是方便管理,二是对系统效率有影响。数据库元组按行存储在硬盘上,访问一个元组时需要将整行读出。如果表中混合了大量不常变的属性,而每次仅修改变动属性,则每次都需要读出整条很长的元组,效率很低。

这个思路的极端结果就是列存储(Columnar Storage)——不是按行存,而是按列存,每一列存储在一个地方。这是大规模数据管理中非常常用的手段。

不能随意合并二元关系

两个二元关系不能随意合并成一个三元关系。在二元关系中 A 和 B 之间没有直接关联,而在三元关系中 A 和 B 有了关联,语义发生了变化。


三、ER 图的设计流程

3.1 局部 ER 图设计

先针对系统的不同用户或不同应用,分别设计局部 ER 图。划分范围的标准是每类用户所涉及的数据范围。

设计步骤:

  1. 确定范围内的实体
  2. 定义每个实体的属性
  3. 定义实体之间的联系

属性分配原则:如果一个属性涉及多个实体类型,一般放在使用频率较高的实体类型上(因为高频使用的表往往会建更多索引,便于查找)。

3.2 局部 ER 图合并为全局 ER 图

以教学管理系统为例,可以围绕三个核心实体分别设计局部 ER 图:

  • 教师:院系、项目、职称、工作量
  • 学生:学会、班级、导师、宿舍、档案材料、社会关系
  • 课程:选修学生、任课教师、教科书、教室、开课院系

合并时,通过公共节点(如教师、学生、课程、院系)将三张图连接在一起,形成完整的全局 ER 图。

3.3 合并时的冲突检查

由于局部 ER 图可能由不同人设计,合并时可能出现以下冲突:

冲突类型 说明 示例
属性类型冲突 同一属性用了不同的度量单位 重量:有的用公斤,有的用克
结构冲突 同一属性有不同的结构 地址:有的是一个字符串,有的分成省/市/区/街道
实体冲突 同一对象在不同图中作为不同类型的实体 有的作为实体,有的作为属性
命名冲突 同名异义或异名同义 同一对象用了不同名字

合并后还要消除冗余的属性。

3.4 ER 图转换为关系模式

实体转换:每个实体转换为一个关系(一张表)。

联系的转换

联系类型 转换方法
二元 1:1 将联系信息放在任意一个实体对应的关系中
二元 1:N 将”1”端的码和联系信息放在”N”端的关系中(如每个员工记录中添加经理工号)
二元 M:N 联系本身单独成为一个关系表,包含两端实体的码
三元联系 联系单独成为一个关系表,包含三个实体的码以及联系自身的属性

对于 1:N 的联系,将”1”端的码放在”N”端的原因是:如果反过来(在”1”端存储所有对应的”N”端),就会形成一个集合,违反关系模式中属性必须为原子值的基本原则。

例题(进货场景):仓库、商店、商品三个实体,以及它们之间的三元联系”进货”(含日期和数量属性)。转换为关系模式:

  • 仓库表、商店表、商品表(每个实体各一张)
  • 进货表(包含仓库ID、商店ID、商品ID、日期、数量)

3.5 第五章与第四章的关系

  • 第五章(ER 图设计):解决属性存在性问题——哪些属性应该放在数据库里
  • 第四章(规范化设计):解决模式好坏问题——ER 图转出的关系模式是否有冗余,如何评价和优化

四、ER 模型的扩展

4.1 弱实体(Weak Entity)

弱实体是指依赖于另一实体而存在的实体,用双线矩形框表示。

例如:

  • 职工的社会关系:社会关系依赖于职工而存在。如果职工离职被删除,其社会关系也随之删除
  • 顾客的通讯地址:地址依赖于顾客而存在

特征

  • 弱实体的存在依赖于其”所有者”实体
  • 弱实体中包含外键指向所有者实体
  • 删除所有者实体时,弱实体也应被级联删除

4.2 继承与子类/超类(ISA Hierarchy)

实体之间也可能存在继承关系——类似于面向对象中的继承概念。

例如:

1
2
3
4
5
人员(身份证号、姓名、年龄、性别)
├── 教师(职工号、职称)+ 继承人员的属性
└── 学生(学号、专业)+ 继承人员的属性
    ├── 本科生(入学年份)+ 继承学生和人员的属性
    └── 研究生(导师、研究方向)+ 继承学生和人员的属性

两种存储策略

策略 做法 优点 缺点
向上存储 每层实体只存自己特有的属性,继承的属性存在父类表中 组织简单,访问哪层就访问哪层的表 连接多(查询一个本科生需要 JOIN 人员、学生、本科生三张表)
向下存储 所有属性都存放在叶子节点对应的表中,父类不单独存数据 减少连接代价 表列会变多,访问量大

4.3 ER 模型在大数据与 AI 时代的新发展

从文本到知识图谱

随着深度学习和大模型技术的成熟,可以从文本中自动提取实体和关系,将一篇文本转化为图结构:

例如一段关于川普和抗议活动的文本,可提取为:

  • 实体:抗议活动、华盛顿特区、川普、美国、总统
  • 关系:发生在(抗议活动→华盛顿特区)、针对(抗议活动→川普)、是(川普→总统)、属于(总统→美国)

将文本转化为图结构后放在数据库中,就可以用数据库高效地做各种查找,成本远低于每次都调大模型。

图数据库(Graph Database)

图数据库将数据存放在图的节点和边中:

  • 节点存放实体信息
  • 边存放实体之间的关系

目前常见的图数据库:

  • Neo4j(最有名的开源图数据库)
  • GDB(阿里)
  • TGDB(腾讯)

大多数国产数据库厂商的配置是:关系数据库 + 图数据库 + 向量数据库(有的还会有时序数据库)。

图数据库的查询语言

  • Cypher(Neo4j)
  • GQL(正在形成的国际标准)
  • SPARQL(用于 RDF 格式的数据)

这些查询语言正在逐步统一,类似于关系数据库中 SQL 统一的趋势。

图数据库的查询类型

除了对节点属性的筛选查询外,图数据库还支持:

查询类型 说明
子图匹配 给出一个模式图,找到数据库中所有匹配的子图
连通性判断 判断两个节点之间是否存在路径
路径查找 按指定的路径模式,找两点之间的所有路径

图数据库的挑战

  • 计算量大:子图匹配是 NP-Complete 问题,最短路径至少是 $O(n^2)$
  • 性能问题:查询涉及大量随机访问,速度较慢

例如,在银行反诈系统中,诈骗资金在账户之间的流转会形成特定的图模式。系统需要实时判断此类模式是否出现,但图模式匹配的效率仍然不足,目前实际中更多采用离线方法进行判断。

图嵌入与图神经网络

为解决图查询的性能问题:

  • 图嵌入(Graph Embedding):将图中的每个节点转化为一个向量
  • 图和图之间的路径查找变成了向量计算,一定程度上提高了效率

但仍有挑战:

  • 图嵌入通常在静态数据集上计算,而数据库是动态场景
  • 向量计算可能有误差
  • 新节点加入时向量的计算方式
  • 这些技术如何应用到数据库系统中仍有大量问题需要研究

五、关系数据库规范化设计引论(第四章概述)

5.1 第四章的核心三要素

  1. 数据依赖(Data Dependency):属性和属性之间的相关性,研究冗余是如何产生的
  2. 范式(Normal Forms):评判模式好坏的若干标准,去除冗余以符合标准
  3. 模式设计方法:根据函数依赖和目标范式,自动将关系模式转化为符合范式要求的模式

三者的关系:数据依赖研究属性间的语义关联 → 范式定义标准 → 模式设计方法实现自动化转换。

5.2 关系模式的内涵(Intension)与外延(Extension)

概念 含义 说明
内涵 关系模式本身 表结构定义、完整性约束、属性间的语义关系、数据依赖
外延 关系模式的实例 具体的数据库表(如”计算机系学生表”“物理系学生表”),表结构和约束都一样,只是数据不同

在证明模式性质时,常用的一种思路是:如果一个性质在该模式的所有实例(所有外延)上都成立,那么该性质在该模式(内涵)上也成立。

5.3 冗余导致的数据异常

以一个设计不当的表为例(包含教师姓名、地址、所上课程):

姓名 地址 课程
T1 A1 C1
T1 A1 C2
T1 A1 C3
T2 A2 C4
T2 A2 C5

T1 上了三门课,地址 A1 出现了三次——这就是冗余。

冗余导致的三种异常:

  1. 删除异常:T3 老师这学期不上课,删除其课程记录时,T3 的地址信息也被意外删除了
  2. 插入异常:T2 老师又上了一门新课,但春节期间他搬家了,插入新课记录时填入新地址,导致 T2 出现两个不同的地址(A2 和新地址),无法判断哪个是正确的
  3. 修改异常:T1 老师搬家了,需要修改地址。由于 T1 有 3 条记录,如果只按课程去修改(如”修改 C3 这门课老师的地址”),只会修改一条,造成数据不一致

5.4 解决方法:分解

将上述一张表拆分为两张:

  • 教师地址表(姓名、地址)
  • 教师课程表(姓名、课程)

分解后,上述三种异常全部消除。

冗余消除的核心原则是避免同一属性出现在多张表中,其核心方法是分表——将一张表拆分为两张或更多。

5.5 非形式化设计指南(经验性方法)

当对表信息掌握不够全面或时间紧迫时,可用以下经验性方法:

  1. 每张表只包含有直接联系的属性:一张表围绕一个主题设计。不要把地址信息和课程信息这两个无关主题的数据放在一起
  2. 避免插入、删除、修改异常:确保数据操作不会产生异常
  3. 避免放置经常为空的属性:如把多种价格作为列,很多列会为空
  4. 尽可能使等值连接在主键和外键属性上进行:系统会为主键构造索引,在主键/外键上做连接效率较高

实际案例:在学校系统中,学生既有学号又有身份证号,都可以唯一标识一个人,但通常选学号(工号)作为主键而非身份证号——因为工号在学校系统中使用更频繁,作为主键更自然。

5.6 符号约定

  • 单个属性:大写字母 A, B, C, …
  • 属性集:大写字母 U, V, W, …
  • 关系模式:大写 R, S, T, …
  • 关系实例:小写 r, s, t, …

5.7 第四章内容预告

第四章分两部分:

  1. 函数依赖、模式分解特性、关系模式范式
  2. 多值依赖及对应的分解方法