数据库三大范式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012410733/article/details/62212363

作为一个web开发者,搞懂数据库是很有必要的。而弄明白关系数据库的三大范式是很有用的。只有清楚了数据库三大范式的设计初衷我们才能够设计出更好的表结构。

1、第零范式

第零范式就是指没有使用任何范式的设计,其添加数据的行为非常诡异,看看下表便知:

假设一个学生学习了三门课程,每门课程都有成绩,那么,采用第零范式的设计将会是如下情况:

student_id name_1 score_1 name_2 score_2 name_3 score_3
1 语文 90 数学 90 英语 98

这样的话,会使得往表中添加数据变得非常麻烦,每次添加一个新的数据,都要添加相应的字段,而且,因为表中其他的记录可能不需要这么多字段,因此会浪费很多空间。如表所示:

student_id name_1 score_1 name_2 score_2 name_3 score_3
1 语文 90 null null null null
2 语文 90 数学 90 英语 98

由此可以看出,不对数据库任用任何范式是非常愚蠢的,因为不仅会产生大量无用的表字段,而且会使得表结构非常难以维护。由此,引出第一范式的介绍

2、第一范式 – 列不可分

第一范式就是指表中的所有字段都是原子的、不可再分的。将第零范式中重复的字段抽取出来,作为表的数据,从而形成一个稳定的、冗余数据少得表结构。

由此,可以得出符合第一范式的表结构应该是:

Student

student_id student_name score
1 英语 90
1 数学 90
1 语文 98

此时,表的结构变得稳定了,而且表中的冗余信息相对第零范式也少了很多。可是,第一范式只是关系数据库设计的最低满足的范式,第一范式中仍然可能有很多的冗余信息,由此,需要引入第二范 式。

3、第二范式 – 非主属性完全依赖主属性

第二范式是满足非主属性完全依赖于主属性。因此,满足第二范式的表当然也是满足第一范式的,第二范式的目的就是消除表中的部分依赖。

这里,有几个概念要解释下,

3.1、完全函数依赖

设有属性集K和P,若K中的所有属性共同能够推出P中的任意属性,且对于K的任何真子集,都不能推出P中的任意属性,则成K完全函数依赖P。

3.2、部分函数依赖

与上相似,只是,K中存在真子集使得,该子集能推出p中任意属性。概念性的东西,往往都难懂,举个例子,方便大家理解:

假如有一张学生成绩表,包含如下属性(学生Id,课程Id,课程分数,学生名字),其中,主键为(学生id,课程id),表中的数据如下:

Student

student_id college_id score student_name
1 2 90 张三
1 1 100 张三

从上面的表数据易知,不满足第二范式的表至少有以下几个缺点:

  1. 数据重复,浪费空间,因为每存一条记录,都要存学生的名字,这样就是得存在大量重复的数据。
  2. 插入异常,若学生还没有成绩,那么这个学生就没有名字。
  3. 更新异常,删除异常等

解决方法:可以分为以下三张表。

Student

student_id student_name

College

college_id college_name

Student_College

student_id college_id score

4、第三范式 – 属性不依赖于其它非主属性

第三范式是指在满足第二范式的情况下,属性不依赖于其它非主属性 , 消除传递依赖

所谓传递依赖,就是指x–>y,y–>z,那么可以得到y–>z.

传递依赖常发生在主键、外键、外键相关的属性上,例如,假设有这样的表

  1. 学生表(学生id,学生姓名,院系id,院系名) ,此处主键为(学生id),外键为(院系id)
  2. 院系表(院系id,院长名称),主键为 (院系id)

Student

student_id student_name college_id college_name
1 carl 1 地理学院
2 alan 1 地理学院
3 kevin 2 外国语学院

College

college_id college_name
1 地理学院
2 外国语学院

从上面的表数据易知,不满足第三范式的表至少有以下几个缺点:

  1. 数据重复,浪费空间,因为学生表每存一条记录,都会记录住院系的名字,存在大量的重复数据。
  2. 插入异常,若新建一个院系,而该院系没有学生的话,该院系就没有名字。
  3. 更新异常,删除异常等

5、反范式

在日常项目中如果完全按照上面的范式设计数据库那么在效率上会存在很大的问题。例如:查询所有的记录信息,这是如果有外检一对多,多对多等关系势必影响系统效率。

另一方面,如果完全遵守范式要求,虽然在一定程度上降低了数据库的yongyu度。但是系统的可维护性会大大的下降。

如果仅仅是这量反面就有足够的理由去做反范式要求了,与其遵守范式要求,不如将更多的业务封装在代码层,这样做的好处就不言而喻了。

反范式设计的目的:用空间去换时间。空间在这里的成本其实是远远低于时间成本的,随着项目的发布,空间成本会越来越低。

6、数据库设计总结

  1. 表的数目不要太多,一般20-30张就够了。如果表的数目太多,则可以考虑采用同化操作,即将大体相同的实体放入到一张表中。
  2. 当数据库中的信息非常庞大时,不要使用外键(逆规范化),因为由此可能带来非常大的性能损失。
  3. 一般以消耗存储空间来换取效率。

三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库。

阅读更多
换一批

没有更多推荐了,返回首页