关系型数据库设计范式总结

Posted YuLong~W

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关系型数据库设计范式总结相关的知识,希望对你有一定的参考价值。

关系型数据库设计范式

范式:Normal Format,符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度

  • 范式是离散数学里的概念,是一种数学理论

  • 范式目标是在满足组织和存储的前提下使数据结构冗余最小化 ,减少数据冗余

  • 范式级别越高,即满足的范式越多,表的级别就越标准,越符合高标准表设计

  • 目前数据库应用到的范式有以下几层:

    • 第一范式:1NF
    • 第二范式:2NF
    • 第三范式:3NF
    • 逆规范化

示例

1、一张员工表

工号姓名部门入职时间
0001杨戬武装部0001-01-01
0002李白书院部1500-12-12

2、每个员工都是与部门挂钩的,但是部门不可能很多,所以上述表中会有很多数据重复,此时应该将部门单独维护出来,减少数据冗余

部门编号部门名称
1武装部
2书院部
工号姓名部门编号入职时间
0001杨戬10001-01-01
0002李白21500-12-12

N个1和N个武装部占用的磁盘空间肯定是不一样的

第一范式1NF

第一范式:1NF,数据字段设计时必须满足原子性

  • 1NF是满足数据表设计的最基础规范
  • 原子性:字段数据颗粒度最小,保证数据取出来使用的时候不用再拆分,就可以直接应用
  • 如果数据使用的时候需要进行拆分那么就违背1NF

步骤:

  • 判断设计的字段是否在使用的时候还需要再拆分
  • 将数据拆分到最小单位(使用),然后设计成字段
  • 满足1NF

示例

1、设计一张学生选修课成绩表

学生性别课程教室成绩学习时间
张三php1011002月1日,2月28日
李四Java102903月1日,3月31日
张三Java102953月1日,3月31日

当前表的学习时间在使用的时候肯定是基于开始时间和结束时间的,而这种设计就会存在使用时的数据拆分,不满足原子性也就是1NF

2、满足1NF的设计:字段颗粒度应用层最小(不需要拆分)

学生性别课程教室成绩开始时间结束时间
张三PHP1011002月1日2月28日
李四Java102903月1日3月31日
张三Java102953月1日3月31日

第二范式2NF

第二范式:2NF,字段设计不能存在部分依赖

  • 部分依赖:首先表存在复合主键,其次有的字段不是依赖整个主键,而只是依赖主键中的一部分
  • 部分依赖解决:让所有非主属性都依赖一个候选关键字
    • 最简单方式:取消复合主键(一般选用逻辑主键替代,但是本质依然是复合主键做主),所有非主属性都依赖主属性(逻辑主键)
    • 正确方式:将部分依赖关系独立成表,不存在部分依赖关系的独立成表
  • 2NF是在满足1NF的前提之上的,2NF可以实现很大程度的数据冗余减少

步骤:

  • 判断表中是否存在复合主键
  • 判断其他字段是否存在依赖主键中的一部分
  • 如果存在部分依赖,将部分依赖的关系独立拆分成表
  • 满足2NF

示例

1、学生成绩表中学生和课程应该是决定性关系,因此属于主属性(主键)

学生(P)性别课程(P)教室成绩开始时间结束时间
张三PHP1011002月1日2月28日
李四Java102903月1日3月31日
张三Java102953月1日3月31日
  • 成绩是由学生和课程决定的,是完全依赖主属性
  • 性别只依赖学生(部分依赖)
  • 教室、开始时间和结束时间依赖课程(部分依赖)

2、解决方案:将学生信息维护到一张表,课程信息维护到一张表,成绩表取两个表的主属性即可

学生表

Stu_id(P)姓名性别
1张三
2李四
  • Stu_id是姓名的代指属性(逻辑主键,本质主键是姓名)
  • 性别只依赖主属性

课程表

Class_id(P)课程教室开始时间结束时间
1PHP1012月1日2月28日
2Java1023月1日3月31日
  • Class_id是课程的代指属性(逻辑主键)
  • 教室、开始时间和结束时间都依赖课程(主属性)

成绩表

Stu_id(P)Class_id(P)成绩
11100
2290
1295
  • Stu_id和Class_id共同组成主属性(复合主键)
  • 成绩依赖Stu_id和Class_id本身,不存在部分依赖

第三范式3NF

第三范式:3NF,字段设计不能存在传递依赖

  • 传递依赖:字段某个非主属性不直接依赖主属性,而是通过依赖某个其他非主属性而传递到主属性之上
  • 传递依赖解决:让依赖非主属性的字段与依赖字段独立成表

步骤:

  • 确定表中的所有字段都是依赖主属性的
  • 如果存在不直接依赖主属性,而是通过依赖其他属性产生依赖的,形成独立的表
  • 满足3NF

示例

1、学生表:包括所在系信息

学号(P)姓名专业编号专业名字
1张三0001001软件工程
2李四0001002土木工程
  • 姓名和专业编号都依赖于学号(为学号提供信息支持)
  • 专业名字依赖专业编号(为编号提供信息支持)
  • 专业名字间接依赖学号:传递依赖
  • 随着学生增加,专业名字会出现大量数据冗余

2、解决方案:将存储传递依赖部分的字段(非主属性)独立成表,然后在需要使用相关信息的时候,引入即可

专业表

专业编号(P)专业名字
0001001软件工程
0001002土木工程
  • 即使有更多的信息为专业提供支持也不存在传递关系

学生表

学号(P)姓名专业编号
1张三0001001
2李四0001002
  • 姓名和专业编号都依赖学号(为学号提供信息支持)
  • 没有其他字段是通过非主属性(专业编号)来依赖主属性的:没有传递依赖
  • 学生再多,专业名字信息只需要维护一次,减少数据冗余

逆规范化

逆规范化:为了提升数据查询的效率刻意违背范式的规则

  • 逆规范化的目标是为了提升数据访问效率
  • 所谓逆规范化就是减少表之间的关联查询(效率降低),刻意增加数据冗余
  • 逆规范化只有在数据量大,查询效率低下的时候为了提升查询效率而牺牲磁盘空间的一种做法
  • 逆规范化后数据表的设计必然是不完全符合范式要求的(2NF/3NF)

步骤:

  • 表中部分数据来源于其他表(通常只需要其他表的某个简单数据)
  • 当前表会被高频次查询
  • 数据表数据量很大
  • 考虑使用逆规范化

示例

1、学生成绩表需要经常查询,而且数据量很大,但是:

  • 成绩表中只有学号,显示的时候需要学生姓名(去学生表中连表查询)
  • 成表表中只有课程号,显示的时候需要显示课程名(去课程表中连表查询)
  • 逆规范化:将学生姓名和课程名在表中冗余维护(不满足2NF)
学号(P)学生姓名课程号(P)课程名字成绩
1张三1PHP100
1张三2Java90
  • 学生姓名部分依赖学号(主属性):不满足2NF
  • 学生姓名和课程名字会有大量数据冗余存在(不满足2NF导致)

总结

1、范式是关系型数据库设计借鉴用来减少数据冗余

  • 1NF:数据字段的原子性,增强数据的可用性
  • 2NF:取消字段的部分依赖,建立数据的关联性,减少数据冗余
  • 3NF:取消字段的传递依赖,将相关实体独立划分,减少数据冗余
  • 逆规范化:为了提升数据访问效率,刻意增加数据冗余(磁盘空间利用率与访问效率的矛盾)

2、在进行数据表设计的时候,需要严格遵循范式规范

  • 基于规范设计数据表
  • 在设计表中深入认知范式规范
  • 熟练的基于业务设计数据表

以上是关于关系型数据库设计范式总结的主要内容,如果未能解决你的问题,请参考以下文章

数据库设计的三大范式

关系数据库设计三大范式

数据库设计三大范式

数据库设计三大范式

数据库设计三大范式

数据库设计三大范式