BCNF
前面提到的第二范式和第三范式分别消除了非主属性对于主属性的部分函数依赖和传递依赖,那么如果主属性对于主键存在部分函数依赖和传递函数依赖会怎么样呢?举个例子,假设:
- 一个数据库公司给多个甲方提供技术支持
- 一个甲方公司现场只需要一名技术支持人员,一名技术支持人员也只能在一个甲方公司做支持
- 一个甲方公司使用了数据库公司的多个产品,每个产品的维护时间都不一样
那么考虑关系模式 现场支持(甲方公司,技术支持人员,项目名,支持时间),它的主键是甲方公司、技术支持人员、项目名。
它是满足第三范式的,因为不存在非主属性对于主键的部分函数依赖和传递依赖。但是它仍然是有问题的:如果技术支持人员被调到另一家甲方公司,那么该技术人员关联的所有记录都要修改;同时,如果一个甲方公司和数据库公司有多个项目,那么甲方公司和技术支持人员都需要重复。所以,满足第三范式的关系模式并不一定能够完全解决前面的问题。针对这个问题,BCNF 就被提出来了,这里给出它的要求:
- 满足第三范式
- 主属性对于主键不存在部分函数依赖和传递依赖
上面的例子主属性(甲方公司)部分依赖于主键(技术支持人员,项目名)。修改之后的关系模式为:
小结
回顾 E-R 关系模型和范式,其实我们可以发现:
- 不满足第一范式的关系模式可能是根本没有建立 E-R 模型,直接将所有信息放到一张表;或者是 E-R 模型没有主键;或者是 E-R 模型转化为关系模式时多值属性、复合属性没有处理好
- 不满足其他范式最大的原因应该是没有正确的识别实体集和关系集。比如第二范式中的例子,会员实体集和图书实体集的信息完全混到了一起;第三范式中图书实体集和出版商实体集混到了一起;BCNF 例子则更可能来自实体集甲方公司、技术支持人员、项目的一个三元关系集。
进一步地,如果 E-R 模型的质量高,那么得到的关系模式满足的更高等级的范式的可能性也会大很多。本人工作经验有限,并没有实际经历完整的建模、规范化,只是从有经验的人了解到大多数业务公司会做的是建模,而规范化比较少。这大概是他们的模型都建立的很好吧(:。当然,实际设计数据库时也不一定要满足范式,比如有时为了业务的方便,也会选择部分数据的冗余。
总结本文只介绍了数据库设计一小部分,这一小部分对于一个高质量的数据库设计是很重要的,但是也是远远不够的。为了得到一个高质量的数据库设计,还需要从两方面去努力。一方面,在 E-R 模型的上游需要做好领域模型的构建,以便于对需要构建的系统有更深入的理解,从而得到更高质量的 E-R 模型。另一个方面,需要非常了解使用的 DBMS 的特性。比如使用 MySQL,需要知道使用哪种类型的存储引擎存储是合适的,使用什么类型的字段是合适的等;有的人还建议不使用关系模式的主键,而是使用自增主键。这两方面也不是完全孤立的,比如要为哪些字段创建索引要基于查询来考虑,而最经常会有的查询其实在业务建模的时候就能明确的。总的来说,数据库设计是一个系统的工程,需要对整个系统都有详细的了解才能做好。