关系型数据库规范化的通俗理解

在大学的时候就已经对数据库范式的概念有所耳闻,可是一直是仅仅知道有这么一个概念。最近参加数据库系统工程师的考试,结合本身的工程经验,终于对数据库规范化理论有了只知其一;不知其二。
本文试图从工程化的角度,用大白话去解释数据库规范化的结论,若是有不严谨之处,敬请指正。我不会去详细介绍每一个范式的严格定义,重复别人的结论没有意义;也不会去解释为何是这个结论,由于我这种俗人已经没办法理解那些神仙证实了!面试

第一范式(1NF)数据库

这个很容易理解,就4个字,原子属性。若是你的关系模式连1NF都不知足,那就是有各类对象嵌套了,这种状况选择一个NoSql数据库可能更合适。数据库设计

第二范式(2NF)函数

在1NF基础上,每个非主属性彻底依赖于码(主键)。编码

概念解释:
一、非主属性:在某关系模式的一组属性中,若是一个属性有可能被选中做为主键(包括多主键的其中一个),它就是主属性,不然就是非主属性设计

二、依赖:依赖和决定是一对,符号表示X→Y,咱们能够说X决定Y或Y依赖于X,例如身份证号与姓名的关系即为:身份证号→姓名。注意要把X和Y当作集合来看待,而不是单一属性!由此能够引伸出一些概念:X→Y且Y是X的子集,就是平凡的函数依赖(工程实践中不多见),不然就是非平凡的函数依赖。若是X的任何真子集都不能决定Y,那么Y对X就是彻底函数依赖,不然就是部分函数依赖对象

理解了上述的概念2NF也就很容易理解了。不少关系模式中的码每每是一个属性集合,只有它的全部非主属性对码都是彻底函数依赖,这个关系模型才符合2NF。下面这个例子就是不符合2NF的:开发

工做经历(公司ID身份证号,姓名,开始时间,结束时间)工程化

关系“工做经历”的码是{公司ID,身份证号},这里面的“身份证号→姓名”显然就是部分函数依赖关系,所以不符合2NF。基础

第三范式(3NF)

在2NF基础上,不存在非主属性对码的传递函数依赖。

概念解释:

一、传递函数依赖:若X→Y,Y→Z,则X→Z成立,Z对X是传递函数依赖。很是简单的概念。

所以3NF也并不难理解,一个不符合3NF的典型例子就是用户管理的场景,在设计开发用户管理模块的过程当中,展现用户每每须要同时展现用户所属的组织机构,这时若是设计用户关系以下:

用户(用户ID,姓名,机构ID,机构名称)

主键为“用户ID”,存在传递函数依赖:用户ID→机构ID→机构名称,显然不符合3NF。

巴克斯范式(BCNF)

在3NF的基础上,消除了主属性对码的部分函数依赖和传递函数依赖。

说白了,就是把2NF和3NF留下的坑给填上了,由于2NF和3NF说的都是非主属性和码之间的依赖关系,BCNF则把主属性也加入到相应的约束之中,能够说,在知足BCNF的关系中,部分函数依赖和传递函数依赖是彻底不存在的。所以从函数依赖的角度来讲,BCNF就是规范化程度最高的关系模式!

在工程实践中,传统的信息系统数据库设计会要求知足3NF,并且咱们习惯于用自增序列或UUID去生成单一的主键,所以咱们设计的数据库通常都是符合BCNF的。

第四范式(4NF)

属性间不容许有非平凡且非函数依赖的多值依赖。

我查阅了一些资料和案例,发现资料上的描述很枯燥晦涩,而案例的描述又语焉不详,为了完全理解4NF,此处采用官方定义与案例结合的方式。下面的多值依赖定义是官方定义。

概念解释:

一、多值依赖

设R(U)是属性集U上的一个关系模式。X,Y,Z是U的子集,而且Z=U-X-Y。关系模式R(U)中多值依赖X→→Y成立,当且仅当对R(U)的任一关系r,给定的一对(x,z)值有一组Y的值,这组值仅仅决定于x值而与z值无关。

上述的定义简单理解就是属性之间存在多对多关系。可是以前我一直不明白的是为何要引入一个看似无关的Z,实际上Z的做用就是判断这个多值依赖是否是平凡的。

若X→→Y,而Z为空集,则称X→→Y为平凡的多值依赖;若Z不为空,则称其为非平凡的多值依赖。

咱们如今构建以下场景:公司安排招聘面试,同一个职位能够属于多个部门,同一个部门拥有多个职位,面试官由员工担任,同一个面试官能够负责多个职位的面试,一个职位也能够由多个面试官参与面试。获得以下关系模式(3属性主键):

面试安排(职位编码部门编码面试官工号

此时设X={职位编码},Y={部门编码},Z={面试官工号};

显然存在X→→Y,而Z不为空集,所以这个多值依赖是非平凡的;函数依赖要求Y的值是被X的一个或一组值惟一肯定的,X→Y只是X→→Y的一个特例,所以X→→Y是非函数依赖的多值依赖。X→→Y这个依赖关系是非平凡且非函数依赖的多值依赖,因此关系模式“面试安排”不符合4NF。同理,X→→Z也是非平凡且非函数依赖的多值依赖。

对关系模式“面试安排”进行符合4NF的分解为:

面试安排1(职位编码面试官工号)面试安排2(职位编码部门编码

则上述两个关系模式中的多值依赖退化成了平凡的多值依赖(由于第三方的Z变成了空集),也就知足了4NF的定义。

还能够对照4NF的官方定义对比:

4NF定义:关系模式R<U,F>∈1NF,若是对于R的每一个非平凡多值依赖X→→Y(Y 不包含于X),X必含有码,则R∈4NF。

对于X必含有码,也就是说主键是它的子集这个要求彷佛很难达到了,所以实际工做中咱们大多数状况下都致力于消除非平凡的多值依赖,让它退化成平凡多值依赖也就脱离了4NF的限制了。

有人提出一个简单的判断4NF的方法就是,对于一个有3个属性的表,给定其中某属性一个值,另外两个属性对应的两列没有多对多关系,那就是4NF。这个方法用于快速判断4NF仍是很可取的。

第五范式(5NF)

这个还没研究过,没有任何工程经验和体会,考试也不会考,想了解的自行修仙吧哈哈!

总结:

在传统的信息系统的构建过程当中,数据库的范式标准越高,对应的数据冗余度就越低,可是系统的关联关系会更加复杂。范式的选择实际上就是数据冗余度与系统复杂度之间的平衡。从经验上来讲,选择3NF或BCNF多是实践的最优解了,但即便如此,依然给应用程序的开发带来了很大的麻烦,当你须要获取业务数据时,每每须要编写大量的链接查询的SQL语句。其实数据库的设计应该提供一套完整的解决方案,应该具有配套的视图、存储过程、触发器以及外键的删除更新级联等以减轻应用开发人员的负担,而非只是完成建表就万事大吉。

最后,做为技术人员,必定不要彻底放弃编码,就像战士永远不要放下手中的剑。保持手感,保持对技术的敏感,不断思考总结,必定会有量变到质变的那一天。