抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文学习了关系数据库中涉及范式的相关知识。

环境

Windows 10 企业版 LTSC 21H2
MySQL 5.7.40

1 定义

设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。

但是有些时候一昧的追求范式减少冗余,反而会降低数据读写的效率,这个时候就要反范式,利用空间来换时间。

2 名词

想要正确理解范式的知识,必须先对涉及到的概念名词有一定的了解。

假设有如下两张表:

  • 学生表:编号,姓名,身份证号,教师编号
  • 教师表:编号,姓名

定义:

  • 实体:可以理解为表,一张表可以看做是一种实体。
  • 属性:可以理解为表的字段,一个字段可以看做是一个属性。
  • 元组:可以理解为表的记录,一条记录可以看做是一个元组。
  • 超键:能唯一标识元组的属性集。对于学生表来说,超键包括(编号),(编号,姓名),(编号,姓名,身份证号)等等。
  • 候选键:能唯一标识元组的最小属性集,是超键的精简。对于学生表来说,候选键就是(编号)和(身份证号)。
  • 主键:从候选键选择一个属性集作为主键。对于学生表来说,主键一般是(编号)。
  • 外键:在其他实体中作为主键的属性集。对于学生表来说,外键是(教师编号)。对于教师表来说,主键是(编号)。
  • 主属性:所有候选键中的属性。
  • 非主属性:不在候选键中的属性。

3 说明

目前关系数据库有六种范式:

  • 第一范式(1NF)
  • 第二范式(2NF)
  • 第三范式(3NF)
  • 巴斯-科德范式(BCNF,又称为修正的第三范式)
  • 第四范式(4NF)
  • 第五范式(5NF,又称完美范式)

满足最低要求的范式是第一范式(1NF),在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。

一般说来,数据库只需满足第三范式(3NF)就行了。

3.1 第一范式(1NF)

要求每个属性都是原子数据项,即每个属性只包含一个值,并且不能有重复的属性。

第一范式确保表中的每个属性都是不可分割的基本数据项。

违背第一范式的数据:

编号 姓名 课程
201010 张三 语文;数学
201011 李四 语文

在课程中存在多个值的情况,违背了第一范式。

修改后的数据:

编号 姓名 课程
201010 张三 语文
201010 张三 数学
201011 李四 语文

3.2 第二范式(2NF)

要求在满足第一范式的基础上,非主属性完全依赖候选键,不能部分依赖候选键。

第二范式确保在候选键为属性组的情况下,表中没有部分依赖问题。

违背第二范式的数据:

编号 姓名 课程 成绩
201010 张三 语文 97
201010 张三 数学 99
201011 李四 语文 94

将编号和课程作为候选键,共同决定成绩,但姓名只依赖编号,存在部分依赖的情况,违背了第二范式。

修改后的数据:

编号 课程 成绩
201010 语文 97
201010 数学 99
201011 语文 94

将编号和姓名单独拆分出来:

编号 姓名
201010 张三
201011 李四

3.3 第三范式(3NF)

要求在满足第二范式的基础上,非主属性只能依赖主属性,不能依赖其他非主属性。

第三范式确保表中没有传递依赖问题。

违背第三范式的数据:

编号 姓名 目标 省市
201010 张三 山东大学 山东省
201011 李四 北京大学 北京市

将编号作为主键,编号决定报考的目标,报考的目标决定所在的省市,存在传递依赖的情况,违背了第三范式。

修改后的数据:

编号 姓名 目标
201010 张三 山东大学
201011 李四 北京大学

将目标和省市单独拆分出来:

目标 省市
山东大学 山东省
北京大学 北京市

3.4 巴斯-科德范式(BCNF)

要求在满足第三范式的基础上,主属性完全依赖候选键,不能部分依赖候选键。

巴斯-科德范式确保在候选键为属性组的情况下,表中没有部分依赖和传递依赖问题。

违背巴斯-科德范式的数据:

编号 课程 教师 成绩
201010 语文 语文老师 93
201010 数学 数学老师 96
201011 语文 语文老师 91

将编号和课程作为主键,同时编号和教师作为候选键,都能决定成绩,但是课程也能决定教师,存在主属性部分依赖候选键的情况,违背了巴斯-科德范式。

修改后的数据:

编号 课程 成绩
201010 语文 93
201010 数学 96
201011 语文 91

将课程和教师单独拆分出来:

课程 教师
语文 语文老师
数学 数学老师

3.5 第四范式(4NF)

要求在满足巴斯-科德范式的基础上,当某个属性的值确定时,只能有一条记录与之对应。

第四范式确保表中没有多值依赖问题。

违背第四范式的数据:

编号 课程 爱好
201010 语文 跑步
201010 数学 游泳
201011 语文 游泳

将编号作为主键,同时对应多个课程和多个爱好,并且课程和爱好之间没有关联,存在多值依赖的情况,违背了第四范式。

修改后的数据:

编号 课程
201010 语文
201010 数学
201011 语文

将编号和爱好单独拆分出来:

编号 爱好
201010 跑步
201010 游泳
201011 游泳

3.6 第五范式(5NF)

又称为完美范式,要求在满足第四范式的基础上,不存在任何通过连接操作生成的冗余数据,即不存在多对多关系。

第五范式确保表中没有连接依赖问题。

违背第五范式的数据:

编号 课程 考试
201010 语文 期中
201010 数学 期末
201011 语文 期末

将编号作为主键,同时对应多个课程和多种考试,并且课程和考试之间存在多对多的关系,存在连接依赖的情况,违背了第五范式。

修改后的数据:

编号 课程
201010 语文
201010 数学
201011 语文

将编号和考试单独拆分出来:

编号 考试
201010 期中
201010 期末
201011 期末

4 反范式化

在某些业务场景下,为了更方便快速的查询数据,往往会打破范式的规范。

反范式化最常见的场景是字段冗余,通过冗余字段可以避免多表联查,大幅提高查询效率。

冗余字段的特点:

  • 通常很少修改。
  • 经常需要查询。

5 设计原则

创建数据库的建议:

  • 库的名称必须控制在32个字符以内,只能使用英文字母、数字和下划线,建议以英文字母开头。
  • 库名中英文一律小写,不同单词采用下划线分割。须见名知意。
  • 创建数据库时必须指定字符集,并且字符集只能是utf8或者utf8mb4。
  • 对于程序连接数据库账号,遵循权限最小原则。使用数据库账号只能在一个DB下使用,不准跨库。
  • 临时库以tmp_为前缀,并以日期为后缀。备份库以bak_为前缀,并以日期为后缀。

创建表的建议:

  • 表和列的名称必须控制在32个字符以内,表名只能使用英文字母、数字和下划线,建议以英文字母开头。
  • 表名、列名一律小写,不同单词采用下划线分割。须见名知意。
  • 表名要求有模块名强相关,同一模块的表名尽量使用统一前缀。
  • 创建表时必须指定字符集,并且字符集只能是utf8或者utf8mb4。
  • 创建表时必须指定表存储引擎类型。如无特殊需求,一律为InnoDB。
  • 创建表时必须说明表的comment内容,说明表的作用。
  • 字段命名应尽可能使用表达实际含义的英文单词或缩写。
  • 字段为布尔值类型时,命名建议为is_描述格式。
  • 字段禁止存储图片和文件等大型二进制数据。建议将文件储存在服务器上,数据库只存储文件地址信息。
  • 表中必须有主键,强制要求主键为id,并设置为int或bigint类型,并且auto_increment自增。
  • 表中必须有行数据的创建时间字段和最后更新时间字段,便于查问题,特别是核心业务相关的表。
  • 表中字段尽量都是NOT NULL属性,业务可以根据需要定义DEFAULT值。因为使用NULL值会占用额外存储空间,会导致数据迁移出错和聚合函数计算结果偏差等问题。
  • 表中存储相同数据的列名和列类型必须一致。相同的字段一般作为关联列,如果查询时关联列类型不一致会自动进行数据类型隐式转换,会造成列上的索引失效,导致查询效率降低。
  • 临时表用于保留临时结果集,名称以tmp_开头。备份表用于备份或抓取源表快照,名称以bak_开头。临时表和备份表定期清理。

创建索引的建议:

  • 主键的名称以pk_开头,唯一键以uni_uk_开头,普通索引以idx_开头,一律使用小写格式,以字段的名称或缩写作为后缀。
  • 单个表上的索引个数不能超过6个。
  • 多考虑建立联合索引,并把区分度最高的字段放在最前面。
  • 表里不能存在冗余索引。

评论