数据库设计规范-三大范式

数据库设计规范

数据库设计的重要性

为什么需要设计数据库?

当数据库比较复杂的时候, 我们就需要对数据库进行设计, 否则会带来以下一些问题:

  • 数据冗余, 浪费空间
  • 数据库插入和删除都会比较麻烦
  • 程序的性能差

而一个良好的数据库设计会为我们带来以下一些好处:

  • 节省内存空间
  • 保证数据可的完整性
  • 方便系统的开发

在软件开发中, 数据库设计分为以下几个步骤

分析需求: 分析业务和需要处理的数据库需求

概要设计: 设计关系图(E-R 图)

数据库设计三大范式

为什么需要数据规范化?

数据规范化是为了避免如下一些问题:

  • 避免信息重复
  • 避免更新异常
  • 避免插入异常
  • 避免删除异常

什么是数据库三大范式?

目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。

满足最低要求的范式是第一范式(1NF), 在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般来说,数据库只需满足第三范式(3NF)就行了, 这也就是我们要讲的三大范式。


第一范式(1NF): 要求数据库的每一列都是不可分割的原子数据项。

举例说明:

学号 姓名 性别 家庭信息 学校信息
20220001 高启强 三口人, 广东 专科, 大三
20220002 孟钰 三口人, 北京 本科, 大二
20220003 徐江 两口人, 上海 硕士, 研三

在上面表格中, "家庭信息"和"学校信息"并不满足原子性的要求, 也就是说不满足第一范式, 调整如下:

学号 姓名 性别 家庭人口 户籍 学历 年级
20220001 高启强 三口人 广东 专科 大三
20220002 孟钰 三口人 北京 本科 大二
20220003 徐江 两口人 上海 硕士 研三

第二范式(2NF): 在第一范式(1NF)的基础上,非属性码的属性必须完全依赖于主码。(在1NF基础上消除非属性码的属性对主码的部分函数依赖)

上面定义中的非属性码我们可以理解为除去主键之外的其他字段, 主码可以理解为主键, 简单说来说: 第二范式在满足第一范式的基础之上, 要求一张表只做一件事情

举例说明: 有如下一张表, 由于在同一个订单中可能包含不同的产品, 因此主键必须是"订单号"和"产品号"联合组成

订单号 产品号 产品数量 产品折扣 产品价格 订单金额 订单时间
2008003 205 100 0.9 8.9 2087 20220103
2008003 206 200 0.8 9.9 2087 20220103
2008005 207 200 0.75 10 2000 20221011

上面表格中联合主键是由订单号和产品号组成, 但是可以发现产品数量、产品折扣、产品价格都是与主键订单号和产品号相关的(完全依赖); 而订单金额和订单时间只与订单号相关(部分依赖); 因此上面表就不满足第二范式, 需要对上面的表进行拆分, 拆分如下:

订单号 产品号 产品数量 产品折扣 产品价格
2008003 205 100 0.9 8.9
2008003 206 200 0.8 9.9
2008005 207 200 0.75 10
订单号 订单金额 订单时间
2008003 2087 20220103
2008003 2087 20220103
2008005 2000 20221011

第三范式(3NF): 在第二范式基础上, 任何非主属性都不依赖于其他非主属性(在2NF基础上,消除传递依赖)。

第三范式需要确保数据表中每一项数据都和主键直接相关, 而不能间接相关

举例说明:

学号 姓名 性别 家庭人口 班主任姓名 班主任性别 班主任年龄
20220001 高启强 三口人 高明远 40
20220002 孟钰 三口人 高赫 30
20220003 徐江 两口人 孙明 20

上表中所有属性都完全依赖于主键学号, 满足第二范式; 但是班主任性别和班主任年龄是直接依赖于班主任姓名的, 而不是直接依赖于主键学号, 所以调整如下:

学号 姓名 性别 家庭人口 班主任姓名
20220001 高启强 三口人 高明远
20220002 孟钰 三口人 高赫
20220003 徐江 两口人 孙明
班主任姓名 班主任性别 班主任年龄
高明远 40
高赫 30
孙明 20

规范性和性能问题:

其实按照三大范式设计出来的数据表并不一定是最合理的, 甚至会影响性能, 阿里开发手册中就明确要求关联查询到表不能超过三张表, 而按照三大范式设计出来的表很容易就超过三张

因此考虑到商业化的需求时, 数据库的性能更加重要, 我们会故意给某些表增加一些冗余字段(从多表查询变为单表查询); 不过在追求性能时, 我们还是需要适当的考虑一下规范性

猜你喜欢

转载自blog.csdn.net/m0_71485750/article/details/128817110
今日推荐