总共有六大范式:
第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。
只记前三范式:
三大范式:
第一范式:数据表中字段满足原子性,字段不可再分
如学生信息字段:存储(张三,手机号),这个可以再分姓名,手机号。不满足
第二范式:满足第一范式基础上,消除部分函数依赖。满足非主键完全依赖于主键
如果存在一个对主键不完全依赖的字段,则不满足第二范式
(学号,姓名,年龄,课程名称,课程学分,学科成绩,系别,系电话) 存在依赖关系: (学号) -> (姓名, 年龄,性别,系别,系办地址、系办电话) (课程名称) -> 学分 (学号,课程)-> 学科成绩 主键 (学号,课程) 学分只依赖主键一部分, 第一个依赖关系只依赖于学号。所以需要将它们进行分离
学生表:(学号,姓名, 年龄,性别,系别,系办地址、系办电话) 课程表:(课程名称,学分) 学生课程表:(学号,课程,学科成绩) 数据冗余:学分重复, 系办地址,系别电话重复 更新异常:调整课程的学分,对应的记录都要修改,可能出现同一门课学分不同 插入异常:由于没人选修课程,没有学号关键字,要等有人选修才能把课程和学分存入
修改复杂:改课程学分,要把设计到课程的所有记录进行修改
满足第二范式的表设计
学生表:(学号,姓名, 年龄,性别,系别,系办地址、系办电话)
课程表:(课程名称,学分)
学生课程表:(学号,课程,学科成绩)
第三范式:第二范式基础上:消除传递依赖;
表中每一列都与主键直接相关,而不是间接相关
X,Y,Z是属性集合。存在X -> Y Y -> Z (Y !-> X)则Z传递依赖于X 比如学生信息表:(学号,姓名,年龄,系别,系电话) 学号 -> 系别 -> 系电话 这个存在传递依赖。 可以拆分两个表。就可以满足第三范式。 学生(学号,姓名,年龄,系别) 系别(系别,系电话)
满足三大范式的优缺点
优点:
范式化的更新操作通常比反范式化要快
当数据较好地范式化时,就只有很少或者没有重复数据,所以只需要修改更少的数据。
范式化的表通常更小,可以更好地放在内存里,所以执行操作会更快
缺点:
通常需要关联,稍微复杂一些的查询语句在符合范式的schema上都可能需要至少一次关联,也许更多。
这不但代价昂贵,也可能使一些索引策略无效。
例如,范式化可能将列存放在不同的表中,而这些列如果在一个表中本可以属于同一个索引。
反范式:
为了解决海量数据中因位大量表连接,数据聚合等操作而带来的性能瓶颈问题。
增加冗余字段:目的是 空间换时间
具体做法是:
在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。
降低范式就是增加字段,减少了查询时的关联,提高查询效率,
因为在数据库的操作中查询的比例要远远大于DML的比例。
但是反范式化一定要适度,并且在原本已满足三范式的基础上再做调整的。
比如文章表,作者,可以增加冗余字段:作者姓名
字段冗余适用于不经常变动的字段。而查询时候需要通过连表获得的字段。
父表建立统计字段,比如 文章会显示对应的评论条数,需要去评论表统计文章出现的对应评论数。
可以在文章表建立评论总数字段,减少大量聚合操作。
知乎上对范式和反范式的理解:
数据库设计应该也是分为三个境界的:
第一个境界,刚入门数据库设计,范式的重要性还未深刻理解。这时候出现的反范式设计,一般会出问题。
第二个境界,随着遇到问题解决问题,渐渐了解到范式的真正好处,从而能快速设计出低冗余、高效率的数据库。
第三个境界,再经过N年的锻炼,是一定会发觉范式的局限性的。此时再去打破范式,设计更合理的反范式部分。
范式就像武侠里面的招数,初学者妄想不按招数来,只能死的很难堪。毕竟招数都是高手总结归纳的精华。而随着武功提高,招数熟练之后,必然是发现招数的局限性,要么忘掉招数,要么自创招数。只要努力,加上多熬几年,总能达到第二个境界,总会觉得范式是经典。此时能不过分依赖范式,快速突破范式局限性的人,自然是高手。
反范式优点就是提高查询效率
参考链接:https://blog.csdn.net/wangqyoho/article/details/52900585