在关系型数据库设计中,如何平衡冗余度与 IO 效率是核心问题。我们需要遵循一定的规范来设计合理的表结构,既要降低数据冗余,又要保证查询性能。
范式概览
范式是一组设计规范,用于指导关系型数据库的设计。常见的有六种范式(1NF 到 5NF),越高的范式对数据约束越强,冗余越小,但可能导致 IO 更繁忙。实际应用中,通常满足第三范式(3NF)即可,若需提升效率,可适度增加字段冗余。
第一范式 (1NF)
第一范式要求数据库表的每一列都是不可分割的原子数据项,不能是集合、数组或对象。
不满足第一范式的例子中,某列包含多个值或对象结构,例如学校信息作为一个整体存储。这违反了原子性原则。

修正后,将对象拆分为独立列,每一列都使用基本数据类型表示,即天然满足第一范式。

第二范式 (2NF)
前提条件:表必须先满足第一范式,且主键为复合主键(由多个字段构成)。
核心要求:所有非主键字段必须完全依赖于整个复合主键,杜绝部分函数依赖。
以选课系统为例,学生选修课程并产生成绩。如果表结构同时包含学号、课程名、姓名、学分和成绩,并使用学号 + 课程名作为复合主键,这里就存在部分依赖:
- 学生姓名、年龄只依赖学号,与课程无关。
- 课程学分只依赖课程名,与学生无关。
这种设计会导致以下问题:
- 数据冗余:学生信息和课程信息在每行重复存储。
- 更新异常:修改课程学分需更新多行,易导致数据不一致。
- 插入异常:新课若无学生选修,无法录入课程信息。
- 删除异常:删除学生成绩可能连带丢失课程信息。
解决思路是将表拆分,确保每张表的主键能唯一标识该行,且非主键列仅依赖主键。

注意:当一张表的主键只有一列时,天然满足第二范式。
第三范式 (3NF)
在满足第二范式的基础上,消除非关键字段对候选键的传递依赖。
举例:学生表中记录所属学院。若表结构包含学生 ID、姓名、学院名、学院电话、学院地址,则存在传递依赖:学生 ID -> 学院名 -> 学院电话。通过学生 ID 找到学院,再通过学院找到电话,中间经过了一层关联。





