范式的理解
范式的理解:
第一范式:字段不可再分,比如爱好,不能保存成字符串拼接的形式。列的原子性。列中不能有多个值。行不能完全重复。
例如:(用户,角色),用户有多个角色,假设角色信息也写在用户表里。不能写成字符串拼接,也不能做成多个角色1,角色2字段,应该做成关系表。消除列存储多个值的冗余行为。
解决方式:将用户与角色的关系抽取成一个关系表。里面包含用户id,角色id,角色名称。
第二范式:完全依赖主键或者联合主键加以区分。不能部分依赖。学号,姓名,课程号,成绩。
例如:(用户,角色)。关系表。(用户id和角色id联合主键,里面如果有角色名称就是冗余的,部分依赖联合主键)。角色名称只与角色id有关,与用户id无关。
解决方式:将角色的信息抽取成一个角色表。(这样形成了用户-角色关系-角色表。这些表没有冗余列,列也没有存储多个值的行为,也没有部分依赖主键,而是全部依赖主键)。
第三范式:传递依赖。(用户,部门,部门经理,职位)。消除冗余的列。字段不可再分,完全依赖主键,但是存在传递依赖。部门经理由部门可以确定,部门由用户可以确定。
解决方式:部门经理字段可以完全去掉。用户想要获得部门经理,查询部门id,部门id查询部门下的人员,通过职位确定部门经理。
借助三范式的理念,我们可以设计出很精炼的数据库表结构。理解范式是做好数据库设计的一门基础,比如选择合适的主键、清晰的划分每一列属性等等。
而实际上的项目应用并不会完全遵循范式的理念,原因在于:
1.性能原因,没有任何冗余的表设计会产生更多关联以至于更多的查询行为,这意味着会产生更多次的数据库IO操作。在一些实时交互的系统中,就会慢得让人难以忍受。
2.数据存储成本,数据库范式是在20世纪提出的,当时的磁盘存储成本还很高。随着科技发展,数据存储的成本已经大幅度缩减,对于采用范式设计(规避冗余)带来的成本缩减收益已经不那么明显。对一些实际数据库应用,以时间换空间就不那么明智了。
反范式化
由于数据库的三大范式和数据库的性能有时是矛盾的。没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。
具体做法是:在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余,达到以空间换时间的目的。
优点 | 缺点 | |
---|---|---|
范式设计 | 尽量的减少数据冗余 表更新操作比反范式化更快 表通常比反范式化体积更小 |
对于查询需要对多个表进行关联 性能降低 更难进行索引优化 |
反范式设计 | 减少表的关联 更好地进行索引优化 |
存在数据冗余及维护异常 对数据的修改需要更多成本 |
三大范式是设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库,为了性能,需要做适当折中,适当牺牲规范化的要求,来提高数据库的性能。