数据库设计一定要遵循三大范式?

文章目录

  • 前言
  • 一、三大范式是什么?
    • 1、一范式
      • 定义
      • 简单的说
      • 举例
    • 2、二范式
      • 定义
      • 简单的说
      • 举例
    • 3、三范式
      • 定义
      • 简单的说
      • 举例
  • 二、一定要符合三大范式?
  • 三、什么情况下需要反范式


前言

前几天在面试百度提前批的时候被问到这个问题,答的不够好,主要是我对这一部分的知识点掌握得不够深入,今天就总结一下关系型数据库的三大范式以及讨论一下数据库设计是否一定要遵循三大范式。

一、三大范式是什么?

**关系型数据库进行设计的时候,一般需要遵循三大范式,**第一范式要求确保表中每列的原子性,也就是不可拆分;第二范式要求确保表中每列与主键相关,而不能只与主键的某部分相关(主要针对联合主键),主键列与非主键列遵循完全函数依赖关系,也就是完全依赖;第三范式确保主键列之间没有传递函数依赖关系,也就是消除传递依赖。

**范式可以避免数据冗余,减少数据库的空间,减轻维护数据完整性的麻烦。但是操作困难,因为需要联系多个表才能得到所需要数据,而且范式越高性能就会越差。要权衡是否使用更高范式是比较麻烦的,**一般在项目中,用得最多的也就是第三范式,用到第三范式也就足够了,性能好而且方便管理数据。

1、一范式

1NF是关系模式应具备的最起码的条件,如果数据库设计不能满足第一范式,就不称为关系型数据库。关系数据库设计研究的关系规范化是在1NF之上进行的。

定义

特征:无重复列
目的:消除实体中列中的重复值或实体的重复属性
每一个属性都是原子项,不可分割。
一范式(First Normal Form,1NF)是关系数据库设计中最基本的范式。它要求数据库表中的每个列都不可分割地保存一个原子值,即每个列都应该是单一值,不可再分解。

简单的说

一范式可以类比为一张二维表格,其中每一行代表一条记录,每一列代表一个属性或字段。一范式要求每个单元格只能保存一个原子值,不能包含多个值或重复的数据。

举例

数据库设计一定要遵循三大范式?_第1张图片

在上面的表中,“家庭信息”和“学校信息”列均不满足原子性的要求,故不满足第一范式,调整如下:数据库设计一定要遵循三大范式?_第2张图片
可见,调整后的每一列都是不可再分的,因此满足第一范式(1NF)

2、二范式

定义

如果关系模式R是1NF,且每个非主属性完全函数依赖于候选键,那么就称R是第二范式。

特征:完全依赖
目的:消除非主属性对主码的部分函数依赖

简单的说

也就是说,每个非主属性是由整个主键函数决定的,而不能由主键的一部分来决定。第二范式可以说是消除部分依赖。第二范式可以减少插入异常,删除异常和修改异常。
它的规则是要求数据表里的所有非主属性都要和该数据表的主键有完全依赖关系;如果有哪些非主属性只和主键的一部份有关的话,它就不符合第二范式

举例

数据库设计一定要遵循三大范式?_第3张图片

这里通过(学生,课程)可以确定教师、教师职称,教材,教室和上课时间。所以可以把(学生,课程)作为主键。但是,教材并不完全依赖于(学生,课程),只用课程就可以确定教材,这就叫不完全依赖,或者部分依赖。出现这种情况,就不满足第二范式。
变更为正确的是:
选课表数据库设计一定要遵循三大范式?_第4张图片
课程表:
数据库设计一定要遵循三大范式?_第5张图片
如果主键只有一个属性,就不会出现部份依赖了。

3、三范式

定义

如果关系模式R是2NF,且关系模式R(U,F)中的所有非主属性对任何候选关键字都不存在传递依赖,则称关系R是属于第三范式

特征:传递依赖
目的:消除传递依赖

简单的说

首先要满足第二范式,其次非主属性之间不存在依赖。由于满足了第二范式,表示每个非主属性都依赖于主键。如果非主属性之间存在了依赖,就会存在传递依赖,这样就不满足第三范式。

举例

数据库设计一定要遵循三大范式?_第6张图片
上例中修改后的选课表中,一个教师能确定一个教师职称。以至于教师依赖于(学生,课程),而教师职称又依赖于教师,这叫传递依赖。第三范式就是要消除传递依赖。
选课表:
数据库设计一定要遵循三大范式?_第7张图片
教师表:
数据库设计一定要遵循三大范式?_第8张图片

二、一定要符合三大范式?

规范化的优点是明显的,它避免了大量的数据冗余,节省了存储空间,保持了数据的一致性。当一个库里的数据经常发生变化时,达到3NF的库可以使用户不必在超过两个以上的地方更改同一个值。

那么是不是只要把所有的表都规范为3NF后,数据库的设计就是最优的呢?这可不一定。

范式越高意味着表的划分更细,一个数据库中需要的表也就越多,用户不得不将原本相关联的数据分摊到多个表中。当用户同时需要这些数据时只能采用连接表的形式将数据重新合并在一起。同时把多个表联接在一起的花费是巨大的,尤其是当需要连接的两张或者多张表数据非常庞大的时候,表连接操作几乎是一个噩梦,这严重地降低了系统运行性能。

所以有的时候不能简单按照规范要求设计数据表,因为有的数据看似冗余,其实对业务来说十分重要。这个时候,我们就要遵循业务有限原则,首先满足业务需求,再尽量较少冗余。

三、什么情况下需要反范式

反范式化设计数据库,当冗余信息有键值或者能大幅度提高查询效率。
一些情况下
比如 存在频繁查询时,可以容忍适当的冗余设计,目的是减少多表关联查询,提高效率
例如:订单表中冗余了商品信息和用户相关信息,避免查询订单时关联用户表和商品表去查询相关信息,提高效率
好查不好改
但是冗余意味着,好查不好改,修改数据时
冗余设计造成需要同时修改多张表中的某些字段

举例1
员工的信息存储在employees表中,部门信息存储在departments表中。通过employees表中的department_id字段与departments表建立关联关系。如果要查询一个员工的部门名称则需要进行join。
如果经常需要进行这个操作,连接查询就会浪费很多时间。可以在employees表中增加一个冗余字段department_name,这样就不用每次都进行连接操作了。

在这种情况下,通过在employees表中增加一个冗余字段department name来存储部门名称,违反了第三范式(ThirdNormal Form,3NF)
第三范式要求一个关系模式中的每个非主属性都不依赖于其他非主属性,即非主属性之间不能存在传递依赖关系。而在这个例子中,department name这个冗余字段依赖于department id字段,而department id本身是一个非主属性。因此,这种冗余设计违反了
第三范式。

举例2

我们有2个表,分别是商品流水表和商品信息表。商品流水表里有400万条记录,商品信息表里有2000条记录。
数据库设计一定要遵循三大范式?_第9张图片

两个表是符合三范式要求的。但是,在我们项目的实施过程中,对流水的查询频率很高,而且为了获取商品名称,基本都会用到与商品信息表连接查询。

为了减少连接,我们可以直接把商品名称字段追加到流水表里。这样一来,我们可以直接从流水表里获取商品的名称了。虽然增加了冗余但是避免了关联查询,提升了查询的效率。

新的商品流水表如下
数据库设计一定要遵循三大范式?_第10张图片

这里也违反了第三范式

你可能感兴趣的:(数据库,开发语言,数据结构)