目录

  • 一、数据库设计的重要性
  • 二、范式 - 简介:
  • 1、什么是范式?
  • 第一范式 - 单一列
  • 第二范式 - 中间表 - 一对多
  • 第三范式 - 不产生中间表 - 一对一、多对一
  • 三、数据库表设计的注意要点
  • 参考链接


一、数据库设计的重要性

良好的表结构设计是高性能的基石,应该根据系统将要执行的业务查询来设计,这往往需要权衡各种因素。糟糕的表结构设计,会浪费大量的开发时间,严重延误项目开发周期,让人痛苦万分,而且直接影响到数据库的性能,并需要花费大量不必要的优化时间,效果往往还不怎么样。

在数据库表设计上有个很重要的设计准则,称为范式设计。

二、范式 - 简介:

1、什么是范式?

范式来自英文Normal Form,简称NF。MySQL是关系型数据库,但是要想设计—个好的关系,必须使关系满足一定的约束条件,此约束已经形成了规范,分成几个等级,一级比一级要求得严格。满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。

目前关系数据库设计有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般来说,数据库只需满足第三范式(3NF)就行了(也就是前三个范式,因为后面的范式是在前面的范式演变过来的,后面的范式包括前面的范式)。

第一范式 - 单一列

定义: 属于第一范式关系的所有属性都不可再分,即数据项不可分。

理解: 第一范式强调数据表的原子性,是其他范式的基础。

将数据库表分为一个单一独立的属性列,比如姓名、年龄、性别、联系电话等等,这便是第一范式,数据库表的原子性。

上表就符合第一范式关系。但日常生活中仅用第一范式来规范表格是远远不够的,依然会存在数据冗余过大、删除异常、插入异常、修改异常的问题,此时就需要引入规范化概念,将其转化为更标准化的表格,减少数据依赖。

实际上,1NF是所有关系型数据库的最基本要求,你在关系型数据库管理系统(RDBMS),例如SQL Server,Oracle,MySQL中创建数据表的时候,如果数据表的设计不符合这个最基本的要求,那么操作一定是不能成功的。也就是说,只要在RDBMS中已经存在的数据表,一定是符合1NF的。

第二范式 - 中间表 - 一对多

第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。

第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一地区分。通常在实现来说,需要为表加上一个列,以存储各个实例的惟一标识。例如员工信息表中加上了员工编号(emp_id)列,因为每个员工的员工编号是惟一的,因此每个员工可以被惟一区分。这个惟一属性列被称为主关键字或主键、主码。

也就是说要求表中只具有一个业务主键,而且第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。什么意思呢?

这句话的意思是一张业务表,要和另外的一张业务表有所联系,那么最最应该设计的是中间表中间表存储了两张业务表的业务关键字。

要特别特别注意:这里的业务关键字可不是指 id 主键,比如员工表里面的员工编号,或者部门表里面的部门编号,这些都是业务关键字段。

这个中间表具体的作用是一个信息包含了多个附属信息,就可以采用第二范式中间表来存储数据,比如一个产品会有多个订单,或者一个订单里面有多个产品等等。
————
| 中间表 |
————
| 1 号产品 id | 1 号订单id |
| 1 号产品 id | 2 号订单id |
————————————
| 1 号订单 id | 1 号产品id |
| 1 号订单 id | 2 号产品id |

第三范式 - 不产生中间表 - 一对一、多对一

指每一个非主属性既不部分依赖于也不传递依赖于业务主键,也就是在第二范式的基础上消除了非主键对主键的传递依赖。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。

具体的设计:

通常遇到一些数据项,会包含了其他数据库表的 id 编号等等,详细的情况是,一对多,但是本身却是多对一,怎么理解这个意思?

这里的 一对一,指的是,该数据只有一个数据项对应一个数据项,但是另外的一个数据项却能对应多个数据项,比如员工只属于一个部门,而一个部门却可以有几百个员工对应。

借用一下图来解释更清楚,下面这张图中,第一张订单表是错误的,产品名称不能接着写进去订单表里面,需要创建一个产品表来存储,不然在订单表里面继续添加产品名称列,那不正是数据冗余吗?多次一举。

mysql数据库 slot MySQL数据库设计_数据库


把订单表里的产品名称删除了,只剩下产品 id 就满足第三范式。

mysql数据库 slot MySQL数据库设计_数据库_02

三、数据库表设计的注意要点

  1. 库名与应用名称保持一致
  2. 表名,字段名必须使用小写字母或数字,且开头不能使用数字
  3. 表名不能使用复数
  4. 表命名规范,业务名称_表的作用
  5. 表必备三个字段,id,create_time,update_time,其中id为主键类型为 bigint unsigned、单表时自增、步长为 1,(如果使用分库分表集群部署,则id类型为verchar,非自增,业务中使用分布式id生成器)
    create_time,update_time 为datetime 类型,前者现在时表示主动创建,后者过去分词表示被动更新
  6. 单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。
  7. 表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint (1 表示是,0 表示否)。
    说明:任何字段如果为非负数,必须是 unsigned。
    正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。
  8. 小数类型为 decimal,禁止使用 float 和 double。 说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不 正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储。
  9. 如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
  10. varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索 引效率。
  11. 唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。
    说明:uk_ 即 unique key;idx_ 即 index 的简称
  12. 不得使用外键与级联,一切外键概念必须在应用层解决。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。