前段时间看完了<MySQL实战45讲>的专栏,想起之前订阅的另一个讲SQL的专栏,就准备一口气看了,和之前的专栏有个对照.
实话说,这个SQL专栏讲的比较浅,因此大部分文章很快地浏览一遍就行.不过其中也有一些内容是丁奇的专栏里没提到的,比如说数据库的设计范式.
那么数据库有哪些设计范式呢?
目前关系型数据库一共有 6 种范式,按照范式级别,从低到高分别是:1NF(第一范式)、2NF(第二范式)、3NF(第三范式)、BCNF(巴斯 - 科德范式)、4NF(第四范式)和 5NF(第五范式,又叫做完美范式)。
数据库范式越高阶,冗余度越低.高阶的范式一定符合低阶范式的要求.
范式涉及到一些主键和候选键的概念.
可以认为候选键是一张表里可以唯一标识一个数据的最小属性集.而主键是从候选键里选出来的.
第一范式是指数据库表里的任何属性都是原子性的,不可再分.所有DBMS都满足第一范式的要求.
第二范式是指数据表里的非主属性都要和这个数据表的候选键有完全依赖关系,不能仅依赖候选键的一部分属性,而必须依赖全部属性.
专栏文章里举了一个不符合2NF的例子,球员比赛表player_game,包含球员编号、姓名、年龄、比赛编号、比赛时间和比赛场地等属性,候选键和主键都为(球员编号,比赛编号).
数据表里存在的对应关系:
(球员编号) -> (姓名,年龄)
(比赛编号) -> (比赛编号,比赛场地)
候选键里的某个字段决定了非主属性.因此会出现数据冗余,插入,删除,更新异常.
比如我们要插入比赛信息,但是此时还没有确定参赛的球员,就无法插入.
删除异常和更新异常和插入异常是类似的.
为了符合第二范式,可以将这张表拆分成三张表:球员表,比赛表和球员比赛关系表.这样每张表都符合第二范式.
其实这和我们编程时经常强调的高内聚低耦合是一样的原理.
原先的表把球员信息和比赛信息耦合在了一起,导致改动球员或比赛的信息都会对另一方造成影响.而将它们解耦成不同的数据表后,就能提高各自模块的内聚性,同时降低模块之间的耦合度.
高内聚,低耦合的系统能更好地应对后续程序的扩展.
数据库高阶范式也是通过降低不同数据之间的耦合度来解决数据彼此强依赖造成的问题.
但是,我们在强调数据库设计范式的同时,也会允许出现一些反范式.比如增加一定的数据冗余来调高查询性能.
然而凡事有利必有弊,增加数据冗余必然会增加不同数据之间的耦合度.这样修改一个数据的同时,就要把冗余的数据全部修改一遍.
没有完美的设计,在不同的场景下,要根据场景的特性来选择适合的设计.以此解决特定问题,力求达到各方面的平衡,并满足最核心的关键指标.
参考文章:
极客时间专栏 <SQL必知必会>




