范式是关系数据库理论的基础,也是咱们在设计数据库结构过程当中所要遵循的规则和指导方法。数据库的设计范式是数据库设计所须要知足的规范。只有理解数据库的设计范式,才能设计出高效率、优雅的数据库,不然可能会设计出错误的数据库。数据库
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,还又称完美范式)。知足最低要求的叫第一范式,简称1NF。在第一范式基础上进一步知足一些要求的为第二范式,简称2NF。其他依此类推。各类范式呈递次规范,越高的范式数据库冗余越小。设计模式
一般所用到的只是前三个范式,即:第一范式(1NF),第二范式(2NF),第三范式(3NF)。数据库设计
第一范式(1NF):强调的是列的原子性,即列不可以再分红其余几列。简而言之,======第一范式就是无重复的列======。性能
第二范式(2NF):首先要知足它是1NF,另外还须要包含两部份内容:一是表必须有一个主键;==二是没有包含在主键中的列必须彻底依赖于主键,而不能只依赖于主键的一部分。==
即要求实体的属性彻底依赖于主关键字。所谓彻底依赖是指不能存在仅依赖主关键字一部分的属性。设计
第三范式(3NF):在1NF基础上,任何非主属性不依赖于其它非主属性[在2NF基础上消除传递依赖]。第三范式(3NF)是第二范式(2NF)的一个子集,即知足第三范式(3NF)必须知足第二范式(2NF)。事务
简而言之,第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主关键字信息。例如,存在一个部门信息表,其中每一个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。若是不存在部门信息表,则根据第三范式(3NF)也应该构建它,不然就会有大量的数据冗余。==简而言之,第三范式就是属性不依赖于其它非主属性,也就是在知足2NF的基础上,任何非主属性不得传递依赖于主属性。==table
关于范式的讨论效率
第二范式和第三范式如何区别?基础
第二范式:非主键列是否依赖主键(包括一列经过某一列间接依赖主键),要是有依赖关系的就是第二范式;方法
第三范式:非主键列是不是直接依赖主键,不能是那种经过传递关系的依赖的。要是符合这种就是第三范式;
使用范式有哪些优势和缺点?
==范式能够避免数据冗余,减小数据库的空间,减轻维护数据完整性的麻烦。==
范式再给咱们带来的上面的好处时,同时也伴随着一些很差的地方:==按照范式的规范设计出来的表,等级越高的范式设计出来的表越多。==
如第一范式可能设计出来的表可能只有一张表而已,再按照第二范式去设计这张表时就可能出来两张或更多张表,若是再按第三范式或更高的范式去设计这张表会出现更多比第二范式多的表。
表的数量越多,当咱们去查询一些数据,必然要去多表中去查询数据,这样查询的时间要比在一张表中查询中所用的时间要高不少。也就是说咱们所用的范式越高,对数据操做的性能越低。
因此咱们在利用范式设计表的时候,要根据具体的需求再去权衡是否使用更高范式去设计表。在通常的项目中,咱们用的最多也就是第三范式,第三范式也就能够知足咱们的项目需求,性能好并且方便管理数据;
当咱们的业务所涉及的表很是多,常常会有多表发生关系,而且咱们对表的操做要时间上要尽可能的快,这时能够考虑咱们使用“反范式”。
关于反范式
不知足范式的模型,就是反范式模型。
反范式跟范式所要求的正好相反,在反范式的设计模式,咱们能够容许适当的数据的冗余,用这个冗余去取操做数据时间的缩短。本质上就是用空间来换取时间,把数据冗余在多个表中,当查询时能够减小或者是避免表之间的关联;
RDBMS模型设计过程当中,经常使用范式约束咱们的模型,但在NOSQL模型中则大量采用反范式。
范式和反范式的对比
模型 | 优势 | 缺点 |
---|---|---|
反范式化模型 | 数据冗余将带来很好的读取性能(由于不须要join不少表,并且一般反范式模型不多作更新操做) | 须要维护冗余数据,从目前NoSQL的发展能够看到,对磁盘空间的消耗是能够接受的 |
范式化模型 | 数据没有冗余,更新容易 | 当表的数量比较多,查询设计须要不少关联模型(join)时,会致使查询性能低下 |
书上讲了好多, 归结起来3句话:
1NF:字段不可分;
2NF:有主键,非主键字段依赖主键;
3NF:非主键字段不能相互依赖;
解释:
1NF:原子性 字段不可再分,不然就不是关系数据库;
2NF:惟一性 一个表只说明一个事物;
3NF:每列都与主键有直接关系,不存在传递依赖;
不符合第一范式的例子(关系数据库中create不出这样的表):
表:字段1, 字段2(字段2.1, 字段2.2), 字段3 ......
存在的问题: 由于设计不出这样的表, 因此没有问题;
不符合第二范式的例子:
表:学号, 姓名, 年龄, 课程名称, 成绩, 学分;
这个代表显说明了两个事务:学生信息, 课程信息;
存在问题:
数据冗余,每条记录都含有相同信息;
删除异常:删除全部学生成绩,就把课程信息全删除了;
插入异常:学生未选课,没法记录进数据库;
更新异常:调整课程学分,全部行都调整。
修正:
学生:Student(学号, 姓名, 年龄);
课程:Course(课程名称, 学分);
选课关系:SelectCourse(学号, 课程名称, 成绩)。
知足第2范式只消除了插入异常。
不符合第三范式的例子:
学号, 姓名, 年龄, 所在学院, 学院联系电话,关键字为单一关键字"学号";
存在依赖传递: (学号) → (所在学院) → (学院地点, 学院电话)
存在问题:
数据冗余:有重复值;
更新异常:有重复的冗余信息,修改时须要同时修改多条记录,不然会出现数据不一致的状况
删除异常
修正: 学生:(学号, 姓名, 年龄, 所在学院); 学院:(学院, 地点, 电话)。