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

    xiaoxiao2023-11-21  8

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

    第一范式(1NF)

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

    第二范式(2NF)

    在1NF基础上,每一个非主属性完全依赖于码(主键)。

    概念解释: 1、非主属性:在某关系模式的一组属性中,如果一个属性有可能被选中作为主键(包括多主键的其中一个),它就是主属性,否则就是非主属性。

    2、依赖:依赖和决定是一对,符号表示X→Y,我们可以说X决定Y或Y依赖于X,例如身份证号与姓名的关系即为:身份证号→姓名。注意要把X和Y当做集合来看待,而不是单一属性!由此可以引申出一些概念:X→Y且Y是X的子集,就是平凡的函数依赖(工程实践中很少见),否则就是非平凡的函数依赖。如果X的任何真子集都不能决定Y,那么Y对X就是完全函数依赖,否则就是部分函数依赖。

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

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

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

    第三范式(3NF)

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

    概念解释:

    1、传递函数依赖:若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,此处采用官方定义与案例结合的方式。下面的多值依赖定义是官方定义。

    概念解释:

    1、多值依赖:

    设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语句。其实数据库的设计应该提供一套完整的解决方案,应该具备配套的视图、存储过程、触发器以及外键的删除更新级联等以减轻应用开发人员的负担,而非只是完成建表就万事大吉。

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

    最新回复(0)