☰
ER图绘制实战:从实体提炼到范式检查的数据库设计流程
2026/10/14 4:35:18 网站建设 项目流程

第一次听到同事说“画实体 ER 图”的时候,很多人会误以为这是个绘图的工作:不就是拿工具把表画出来嘛,字段一拖、连线一拉,就算交差。我在几个项目里见过太多次这种误解,最后往往演变成一群人对着一张大而全的图争论“这个字段是什么意思”“这两张表为什么要连在一起”“外键到底有没有必要”。真正的问题在于,ER 图承载的是数据库设计决策,不是美术作品。你画什么、不画什么、怎么连、基数标在哪,这些动作背后全都是业务规则和技术取舍。想把这件“动鼠标”的小事做成“定结构”的正事,需要的是一套成型的方法和一个顺手工具。这篇内容就是想把我在实操中反复踩坑之后沉淀下来的一套流程讲清楚,覆盖实体提炼、关系标注、范式检查、工具选型和常见排查,给正在为某个新模块设计表结构、或者对着旧库反推模型的你,提供一份能直接抄作业的参考思路。

1. 先搞明白你画的是哪一层的 ER 图

1.1 概念模型、逻辑模型、物理模型,别混在一张图里画

“画 ER 图”这个词听起来很统一,但真实工作里至少有三个层次,混着画是新手最容易犯的错误。概念模型描述业务里有哪些实体和联系,不涉及主键、字段类型,常常用来和业务方对齐需求,画出来像一张业务流程图,框里写着“客户”“订单”“商品”。逻辑模型开始接近表结构,实体变成了表,属性变成了字段,关系有了基数,但这个阶段还不关心数据库特性。物理模型则要完全针对你选定的数据库,字段类型、长度、默认值、索引、分区,全部落地。

我见过不少人一上来就打开建模工具,从物理模型开始画,每个字段都往细了抠——类型选BIGINT还是VARCHAR(36),要不要DEFAULT——基础表还没讨论明白,整个版面已经被字段塞满了。这时候再去讨论“这个业务关系到底是什么”,所有人的注意力都会被字段级的细节带走,反而把最核心的关系设计给模糊了。更好的做法是分层推进:先用概念模型说清业务边界,确认实体和关系没问题,再往逻辑模型细化字段,最后才转成物理模型。

打个比方,同一栋建筑,你要给业主看的是概念效果图,给施工队看的是结构施工图,给水电班组看的是管线图。画 ER 图同理,把三层内容塞进同一张图,只会让读者无所适从。我现在的习惯是:概念模型在文档和评审会上用,逻辑模型进入日常讨论流转,物理模型真正对接建表和脚本生成。三个模型之间保持可追溯的映射关系,模型一变,对应层的图就跟着更新。

1.2 识别实体,靠的是两把尺子而不是语感

实体识别这件事,很多人靠“找名词”来凑数。需求文档扫一遍,把名词都捞出来,然后变成候选实体。这办法不能说完全错,但很容易捞出一堆“假实体”。我之前接手过一个内容管理系统的需求,业务方列了一堆名词:文章、作者、分类、标签、评论、点赞、审核记录、阅读量。如果全按名词建表,阅读量和点赞数就很容易被当成字段塞进文章表里,但实际上它们可能依赖大量统计逻辑,应该单独设计。

我判断一个候选词是不是实体,一般用两把尺子。第一把尺子叫“属性独立性”:这个东西是否拥有一组稳定的、区别于其他实体的属性?比如“点赞”,它的属性只有“谁点的、什么时候点的”,看起来像文章表的下级字段,但当它需要记录“点赞的是哪个人”并且未来可能统计“这个人点过什么”的时候,它就应该被提出来成为实体“点赞记录”。第二把尺子叫“生命周期”:这个东西是否会独立于其他实体被创建和删除?比如“审核记录”拥有自己的创建时间、审核人、审核结论,并且审核这个动作独立于文章内容,就应该单独建模。

这两种判断标准结合起来,能帮你避开“把所有名词都建表”或“把所有属性都堆主表”两个极端。概念模型阶段不要求你一次就把边界定死,实体是不是要独立成表,留到逻辑模型里用范式规则再校验一次,但实体清单最好在这个阶段就尽量收敛,否则后面改动的连锁反应很大。

2. 工具不是越贵越好,按场景选才顺手

2.1 三条路线对应三类协作场景

工具选择是默认的杂音,很多人在网上搜“ER 图工具”然后直接下载一个,画了两张发现同步困难又换。我在时机浪费上踩过坑,所以现在更推荐你根据团队协作方式选路线,而不是迷信某个单机软件的名气。

第一条路线是在线白板式绘图,适合需求的早期沟通。这类工具几乎不需要学习成本,拖拽、连线、加便签,业务方一样看得懂。优点是即时分享、协同改图方便,适合在评审会上现场调整。缺点也很明显:和真实表结构没有联动,画出来的“图”常常和最终数据库对不上,一旦代码变了,图可能永远停在很久以前的版本。第二条路线是文本代码式绘图,用描述性的语法生成图形。这种方式适合长期维护,因为图就是一份文本文件,可以放进 Git 仓库跟随代码一起做版本控制。改动点什么,可以直接在代码评审里看到差异,非常稳。代价是配置连接线、定位布局得有学习成本,前端业务同学操作也不方便。第三条路线是数据库配套建模工具,适合正向建库或反向解析已有库。它能直连数据库、读取表结构、自动排布关系线,也能从图形模型里生成或同步 DDL,本质上就是给建模过程提供双向通道。缺点是有些模块用起来偏重,尤其是在大项目里自动布局容易乱,如果不理解数据库结构,生成的图区分不出主外键关系,反而增加混乱。

路线适合场景关键技术优势主要痛点
在线白板式需求对齐、方案评审零门槛、协作直观与真实表结构脱节,容易过时
文本代码式长期维护、版本管理可 diff、可复用、适合多人并行绘图语法有门槛,布局调整费时
数据库建模工具正向建库、逆向解析字段、索引、外键直接同步自动排布对复杂 schema 不友好

在实际项目里,这三条路不是非此即彼。我自己固定下来的组合是:日常维护用某个代码式工具,因为要跟着代码分支走;接到旧系统时用数据库建模工具直接逆向;给业务方讲需求的时候,再画几张白板式的概念图。能坚持用下去的组合,永远比工具本身更重要。

2.2 正向建模还是逆向工程,先后次序决定一半效率

工具确定后还有两条相反的工作流要选择。正向建模是从业务需求出发,先画概念模型,再逐步生成物理模型和建表语句,适合全新系统或新模块。逆向工程则是把已经存在的数据库表结构导入建模工具,反向生成 ER 图,适合接手旧项目、梳理存量模型时使用。两条路各有坑。

先说正向建模。看着一片空白画布,很多新人会陷入“想一步到位”的陷阱,试图把每个字段的类型、每个索引都完美设计完才动手画。其实正向建模最有效的节奏是先粗后细,把实体和关系先铺开,统一确认逻辑模型,再考虑物理优化。还有一点我反复强调过多次:正向建模的产出不仅是“最终图”,更应该包括中间勾兑出来的设计说明。记录下“为什么这个关系是可选的”“为什么这个字段放 A 表而不是 B 表”,后续维护才有人接得住。

再说逆向工程。它看似省力,连接数据库点一下就能生成图,但我实在地体会到一个致命前提:数据库里外键定义得不全,逆向出来的 ER 图就是一盘散沙。很多系统在建表时为了写入性能和开发便利,并没有在物理层明确外键,只靠业务代码里的逻辑关联承担关系。这个结果在逆向时根本不会出现,模型图里表是表、线是线,比手工检查更费劲。遇到这种情况,我的方案是先把可辨识的命名规范(比如每张表有xxx_id字段)统一对一遍,把明显的外键关系在工具里手动补上,再让建模工具自动布局,最后仍需人工确认一遍隐藏的关系。

3. 一套能直接抄的 ER 图绘制流程

3.1 从需求描述里提炼实体和初步关系

拿一个贴近现实的小项目做例子。假设你要做一个“企业内部通知系统”,核心需求只有一句话:员工可以发布通知,其他员工可以阅读、评论并定期收藏重点通知。整套流程从这句话就开始运转。

第一步是把一句话拆成短语:员工、发布通知、阅读通知、评论通知、收藏通知。第二步按 1.2 里的两把尺子过一遍:“员工”有独立属性和完整生命周期,是实体;“通知”有标题、正文、发布时间等字段,也是实体;“评论”和“收藏”虽然依赖通知存在,但都有自己额外的产生时间和关联人,这个阶段先保留为实体。“发布”是动作,不单独建模,作为“员工到通知”的关系处理;“阅读”是行为统计,先不纳入核心关系,后期如果要统计阅读量,再考虑单独记录。

经过筛选,第一步得到的候选实体清单是:员工、通知、评论、收藏。初始关系是:员工可以发布通知(员工 → 通知)、员工可以评论通知(员工、通知 → 评论)、员工可以收藏通知(员工 ↔ 通知,多对多)。这张初始图不需要精致,线连起来即可,重要的是实体和关系都已经摆在台面上,接下来才有细化的对象。

3.2 把关系细化成基数、可选性和外键

关系画成一条线,但这条线上承载的信息量很大。每个关系都要回答两件事:基数是多少,参与方是否可选。

“员工发布通知”这个关系,一个员工可以发布多条通知,但一条通知只能由一个员工发布,所以基数是 1:N,通知端的可选性要按业务规则判断。如果系统允许系统管理员代发通知,那么通知的发布人可能为空,发布人这个外键是可选的。我建议把这个分析过程放到图中,不要只在脑子里过。用标识关系的时候,把可选性符号标在全外键的那一端,这样生成建表语句的时候就知道该字段是否NULL。

“员工收藏通知”是典型的多对多关系。一个员工可以收藏多条通知,一条通知也可以被多个员工收藏,这种关系不能简单用一方的主键放在另一方表里解决,需要引入中间表“收藏”。中间表至少包含员工ID、通知ID、收藏时间,员工ID和通知ID一起构成联合主键。联合主键在某些场景下够用,但如果你预期未来要做收藏分组、收藏排序等功能,给中间表加一个代理主键列会更灵活。这里是设计取舍,不是简单对错。

可选性判断有三个最常用的依据:业务规则是否强制、是否可能缺少值、字段值在创建后是否会变化。用这些依据把每条关系过一遍,画图过程中就能顺手把约束也定下来,这一步替后期省下的返工时间相当可观。

3.3 用范式检查把看不见的冗余揪出来

关系画完,图面上看起来已经像模像样了,但很多“隐性表”还没浮现出来。比如“通知”表里如果直接放了“发布人姓名”,而“姓名”又和“员工表”里的字段保持一致,这个字段就是冗余的。为了让这种冗余在画图阶段现形,我会把相图画完的初稿停下来,做一趟范式对照检查。

第一范式要求字段不可再分,每个单元格只能存一个值。喜欢把标签用逗号拼成一个字段的做法,在第一范式这里就会触雷。第二范式关注复合主键下是否出现了部分依赖。凡是复合主键表里的字段,必须依赖全部主键,不能只依赖其中一部分。这个规则对“收藏”表特别有意义:如果往收藏表里加了“通知标题”这个字段,它只依赖通知ID,不依赖收藏的员工ID,就是部分依赖,应该拆出去。第三范式要求字段不能依赖于其它非主键字段。最普遍的表达就是“员工表存部门名称”,其实部门名称依赖于部门ID,而不是员工的个人信息,正确的做法是拆出部门表,用部门ID关联。ER 图阶段做范式检查,成本比建表后再改低太多。建表之后要改,涉及数据迁移、接口变化、统计口径调整,可以说牵一发而动全身。而在图的逻辑模型里,改动就是画几个框、挪几条线,确认时间可以压缩到几分钟。

3.4 从物理模型到建表语句的一次性生成

逻辑模型确认完毕后,开始进入物理模型。给实体设定字段类型时,主键的选择要想清楚逻辑主键和业务主键的关系。比如员工号如果用工号,一旦工号调整,所有关联引用的同步成本很高。更常见的做法是使用无业务含义的自增整数或 UUID 作为代理主键,把工号这类业务字段作为普通唯一键。

模型梳理到可以落库的程度后,最理想的路径是让建模工具直接生成 DDL,而不是自己手工编写。手工写建表语句很容易漏掉索引、字符集、外键约束这些细节。生成时要注意一个顺序性问题:建表语句必须先创建被引用表,再创建引用表,否则外键约束会因引用表不存在而失败。大多数建模工具会照顾这一点,但如果你用代码式施工方式,还是自己组织一下顺序更稳妥。下面这段是示例风格的表达,实际工具生成的脚本略有差异,但结构一致:

CREATE TABLE employee ( emp_id BIGINT PRIMARY KEY, emp_name VARCHAR(32) NOT NULL, dept_id BIGINT, create_time DATETIME NOT NULL ); CREATE TABLE notice ( notice_id BIGINT PRIMARY KEY, title VARCHAR(200) NOT NULL, content TEXT NOT NULL, publisher_id BIGINT, publish_time DATETIME ); CREATE TABLE favorite ( emp_id BIGINT NOT NULL, notice_id BIGINT NOT NULL, favorite_time DATETIME NOT NULL, PRIMARY KEY (emp_id, notice_id), CONSTRAINT fk_fav_emp FOREIGN KEY (emp_id) REFERENCES employee(emp_id), CONSTRAINT fk_fav_notice FOREIGN KEY (notice_id) REFERENCES notice(notice_id) );

脚本生成后并不等于流程结束,最好再把核心表关系的 DDL 和逻辑模型比对一遍,看看有没有“图中说好了是一对多,脚本里却变成了一对一”这类偏差。这一步像一个前后校准器,保证模型图与真实库保持一致。

4. 实战高频坑位与排查技巧

4.1 图看起来没错,但库和行为差一截

这类问题是排障记录里出现频率最高的。第一类错误是把多对多关系直接添加字段绕过去,不建中间表。短线图不敢乱画代价是后面统计收藏人数时写出复杂的聚合 SQL。如果发现某个关系在查询时总是要借助字符串拼接,大概率是少了中间实体。第二类错误是把“状态”当成属性还是实体搞不清。一个字段叫“审核状态”,如果它只是0/1/2的枚举值,放在通知表里没问题。但一旦状态有流转记录、有操作人,就必须上升到独立的“审核记录”实体,否则审计完全不可靠。第三类是主键语义混淆。把唯一业务编号直接当主键用,工号一改,全链条跟着动。第四类是 ER 图和库不同步。早前画的图在文档里被尊为经典,库却因为迭代早就变了,后来人看图犹如看史书。第五类是关系缺少可选性考量,把可空字段设计成NOT NULL,结果业务数据一进来就报错。

排查这些问题的有效办法,是用一个简单检查表:每个关系是否落到外键字段;每个多对多是否都有中间表;每个含复合主键的表是否满足第二范式;每个非主键字段是否只依赖整个主键;图中字段是否和真实库字段一一对齐。逐行打勾,很多问题都会现形。

4.2 表数量过一次,图就开始挑战人类视力

当表数量超过 30 张,把全部实体画在一张画布上必然变成蜘蛛网。这不是工具不好,而是方法问题。我建议做分层梳理。第一步按业务域分组,比如把通知域、员工域、收藏统计域分开。每组单独产出一张主题图,图内只画本域实体及跨域的外键引用。第二步建立“域间关系总图”,只画域和域之间的实体依赖,不展开字段,起到导航作用。这样你就有了多张可读性很强的图,而不是一张巨型地图。

图形表达上还有几个实用小建议:实体按类型用不同底色区分,核心实体用暖色,关联实体用中性色,配置类实体用冷色;外键字段加特定前缀标识;在画布角落留一个图例说明符号含义。不要小看图例,半年前画的东西,半年后连自己都要靠图例回忆。

4.3 评审会上最容易被问倒的三个问题

ER 图已经画好,带着去评审,几乎每个人都会被问到类似的三类问题,提前准备能省很多尴尬。

第一类:“这个多对多中间表为什么不用单一自增主键,而用联合主键?”如果中间表没有独立业务含义,联合主键能防止重复收藏,本身就是约束的表达。如果中间表后续要扩展分组功能,单自增主键再加唯一索引也能做,但要解释清楚为什么放弃联合主键。这个问题的本质,是检验你有没有想清楚约束优先级。第二类:“为什么这里没有外键?”很多系统确实会物理省略外键来降低锁竞争和写入开销,但图里一定还得体现这层关系,并在文档里注明“逻辑外键,无物理约束”。这个备注非常关键,不然数据库迁移、级联删除、ORM 映射推理都会踩坑。第三类:“这个可空字段为什么允许为空?”要能讲出对应的业务场景,比如“通知允许没有发布时间”在设计上是有意为之,给草稿通知留空间。最怕的就是说“我也不知道为什么可空”,那意味着图里藏着一个你都没搞清楚的设计妥协。

5. 养成“模型优先”的习惯

流程图和文档都做完之后,最值得分享的一个心得是把顺序真正反过来:先画图,再写代码,最后才建库或同步。听起来像老生常谈,但我见过太多次团队在赶进度时反过来操作,代码先写着,表先建着,回头再补模型图,结果模型图只能当项目汇报里的配图,一点设计价值都没有。真正从模型优先中受益的健康状态是:每一次结构变更,先在模型层说清楚影响,再改代码。刚开始会显得繁琐,但试过一两个迭代就会明显感到变更评审的成本降了不少。

我自己现在还保留着一个习惯:每到一个新项目,会先把“关系和约束清单”单独整理一页纸,放在 ER 图旁边。比如“通知发布人的可空性取决于是否允许代发”“收藏时间和收藏人都不允许为空”,这些规则写在图旁边,图才真正有了生命力。换句话说,图是结果,规则是原因,画图只是把思考可视化的手段。如果你正在摸索这个流程,愿望不要定太高,从一个小模块开始实践,把工具链和分层方法走通,比直接在大型项目上强行推动要稳妥得多。等你感受到“改模型比改数据轻松太多”的瞬间,大概率就再也不会回到盲写建表语句的日子了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询