刚入职那会儿,我对数据库其实没多少感觉。上一家公司对产品经理的要求很简单:能写几条基础 SQL,查查数据、辅助分析就够了。至于表结构怎么设计、字段之间怎么关联,那都是研发和架构师的事情。
但后来我慢慢发现,事情变了。特别是做 B 端产品,你不可能永远只站在“界面”那层看问题。最近随手翻几家大厂的 B 端产品经理 JD,“了解主流数据库原理,具备较强的数据库设计能力”几乎成了标配。这里说的“数据库设计能力”,多数时候指的就是逻辑设计——你能不能把业务规则,用表和关系清晰地翻译成数据模型。
所以这篇文章,我就从一个产品经理的视角,用我们最常接触的 RBAC 权限管理模块,把数据库逻辑设计的过程完整走一遍。不讲高深理论,就是想还原一个真实的设计现场。
数据库设计说到底,就是根据业务系统的实际需求,选好数据库,然后设计出最合适的数据存储模型——包括建哪些表、表里放哪些字段、表跟表之间怎么关联。目的就两个:高效地存数据,高效地取数据。这有点像盖楼打地基,地基歪了,上面的功能再花哨也容易出问题。好的设计,表结构清晰,没有太多冗余,关联自然,查询也快;差的设计,表里塞满各种字段,改一个需求要动全身,数据一致性和性能都很难保证。

一个完整的数据库设计,通常可以分成三个阶段:需求分析、逻辑设计、物理设计。产品经理真正要深入参与的,是前两步,尤其是逻辑设计。
第一步,需求分析:别急着建表,先想清楚数据怎么用。
这一步,你得把系统里要存的数据都捋一遍:它们有什么属性,是长期有效还是有过期时间,数据量增长快不快,哪些是核心数据,哪些只是辅助。举个例子,有些数据有很强的时效性,比如小米云服务里,用户删除的照片会先进回收站保留一段时间,到期自动清空。这种“过期清理”的机制,就需要在设计时提前想好——是直接物理删除,还是先标记为逻辑删除,再定期清理。
再比如,数据量大、增长快但不是核心的数据,可以考虑分库分表。我之前接触过一个客户,需要给用户批量发邮件,系统会不断返回邮件的状态信息。这些状态数据量极大,很快就能达到几千万行。如果全塞在一张表里,用户打开列表页就会卡得不行,搜索、翻页都慢。这时候,数据库的“水平分割”就派上用场了,把数据分散到多张结构相同的表里,查询时只查对应的那一张,效率就上来了。
回到我这次要做的 RBAC 权限管理,我把功能拆成四个核心模块:组织架构、角色、菜单权限、人员管理。然后,我逐一梳理每个模块对应的实体属性,并确定主键和外键。
组织架构模块,需要存组织 ID、组织类型、组织名称、单位类型、联系人、邮箱、电话等。主键可以选组织 ID,也可以是组织名称,看业务上是否允许重名。存储特性:永久保存。
角色模块,包括角色 ID、角色分类、角色名称、角色描述、排序 ID、创建者、创建时间等。主键同样可以选角色 ID 或角色名称,永久存储。

菜单权限模块,属性有菜单 ID、排序 ID、菜单名称、菜单路径 URL 等。主键可选菜单 ID 或菜单名称,永久存储。
人员管理模块,需要用户 ID、姓名、单位职位、等级、手机号、登录名等。主键通常用人员 ID,也是永久存储。
这一步做完,我手里就有了一份清晰的“数据清单”,接下来就可以进入逻辑设计了。
第二步,逻辑设计:画 ER 图,用范式把表结构捋清楚。
这是产品经理的重头戏。我们要把需求分析里的实体和关系,用 ER 图表达出来,然后再用数据库范式去规范表结构。ER 图有标准画法:矩形是实体,菱形是关系,椭圆是属性,线段连接它们。实际工作中,我习惯先在纸上画个草图,理清谁和谁有关联,再慢慢细化。
比如,组织架构和人员之间,一个组织可以有多个人员,一个人员只能属于一个组织,这就是一对多关系。人员和角色之间,一个人员可以有多个角色,一个角色下面也可以有多个人员,这就是多对多关系。
接下来,要用数据库范式来“格式化”这些表。范式听起来很抽象,但用案例解释就很好懂。

第一范式要求每个字段不能再分。这是最基础的要求。比如你设计一个“联系人信息”字段,它里面其实包含了邮箱和电话,这就违反了第一范式。正确的做法是拆成“邮箱”和“电话”两个独立字段。这个要求最容易满足,基本上就是保证表是一个二维表,每个格子都是原子值。
第二范式要求消除部分依赖。在第一范式的基础上,表里的非主键字段必须完全依赖于主键,不能只依赖主键的一部分。假设我把组织结构和人员信息全塞在一张表里,比如一张“组织人员表”,有组织 ID、组织名称、人员 ID、姓名、手机号等。这张表的主键可能是(组织 ID,人员 ID)的组合。但组织名称只依赖于组织 ID,不依赖于人员 ID,这就产生了部分依赖。所以,要拆成两张表:组织结构表(组织 ID,组织名称等)和人员管理表(人员 ID,姓名等),再通过一张关联表把两者连起来。这样每张表里的非主键字段都完全依赖于自己的主键。
第三范式要求消除传递依赖。也就是说,非主键字段不能依赖于其他非主键字段。典型场景比如:人员管理表里,如果直接存了角色名称,那当这个人员有多个角色,或者角色名称修改时,就会出现数据冗余和更新异常。因为角色名称其实依赖于角色 ID,而角色 ID 又依赖于人员 ID,这就形成了传递依赖。正确的做法是:人员管理表只存人员自己的信息,角色信息单独建角色表,再用一张关联表保存人员 ID 和角色 ID 的对应关系。这样,你想查某个人员的角色名称,通过关联表去角色表里查就行,数据干净,修改也方便。
简单来说,第一范式要求字段原子化;第二范式要求一个表只描述一件事,消除部分依赖;第三范式要求在已经拆表的基础上,消除传递依赖,让表之间只通过主键关联。当然,实际设计中还有反范式化——有时候为了查询性能,故意冗余一些字段,但那是后话了。作为产品经理,理解到第三范式,已经足够应对大部分逻辑设计场景。
结合范式和 ER 图,我最终输出的 RBAC 表结构大概是这样的:
- 组织结构表(组织 ID、组织类型、组织名称、单位类型、联系人、邮箱、电话)
- 角色表(角色 ID、角色分类、角色名称、角色描述、排序 ID、创建者、创建时间)
- 菜单权限表(菜单 ID、排序 ID、菜单名称、菜单路径 URL)
- 人员管理表(用户 ID、姓名、单位职位、等级、手机号、登录名)
- 人员-角色关联表(用户 ID、角色 ID)
- 角色-菜单关联表(角色 ID、菜单 ID)
这里为了方便理解,字段名我都用中文写了,实际落地时都得换成英文,比如 UserId、RoleId 之类。这个命名工作,一般在后面的物理设计阶段由架构师统一定义。
第三步,物理设计,这一步主要交给架构师,但你可以了解个大概。物理设计就是选择具体的数据库管理系统,比如 MySQL、PostgreSQL,定义数据库、表、字段的命名规范,以及根据 DBMS 的特性选择合适的字段类型,比如用 varchar 还是 text,用 int 还是 bigint。这部分产品经理一般不需要深入,知道有这回事就行。
最后说几句。掌握这些知识,并不能让你立刻成为数据库专家。数据库设计里,要在业务需求、查询性能和数据冗余之间找到平衡,是需要大量实战积累的。但至少,通过这样一次完整的逻辑设计梳理,你能够理解最基本的建表思路,知道怎么把业务规则变成表结构,这对理解系统底层、和研发顺畅沟通,帮助非常大。而且,有了这些基础,再去学 SQL,也会觉得更通透。

希望这篇文章,能给正在往 B 端深水区走的产品经理们,带来一些实实在在的启发。
Login Now