数据库表格设计原则

数据三范式

总关系是依次递进

1. 第一范式(1NF)--确保原子性:

列的原子性,不能再拆分其他几列

2. 第二范式(2NF)--确保表中每列都和主键相关:

先满足1NF,然后每张表要有主键,并且确保每一列都和主键相关,而不是主键的一部分(主要针对联合主键)。换言之,一个表中只保存一种数据而不是多种数据。
错误示范中,订单编号和商品编号作为联合主键,但商品信息只跟商品编号有关。

数据库表格设计原则_第1张图片
商品订单信息错误设计

正确示范:
数据库表格设计原则_第2张图片
商品订单信息正确设计

3. 第三范式(3NF)--确保每列都和主键直接相关,而不是间接相关

第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。不能传递依赖,如非主键列A依赖非主键列B,非主键列B依赖主键。
关键字段 → 非关键字段x → 非关键字段y

  1. 例子一:比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。如下面这两个表所示的设计就是一个满足第三范式的数据库表。
    数据库表格设计原则_第3张图片
    订单信息和客户信息
  1. 例子二:假定学生关系表为Student(学号, 姓名, 年龄, 所在学院, 学院地点, 学院电话),关键字为单一关键字"学号",因为存在如下决定关系:

(学号) → (姓名, 年龄, 所在学院, 学院地点, 学院电话)

这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系:

(学号) → (所在学院) → (学院地点, 学院电话)

即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。
它也会存在数据冗余、更新异常、插入异常和删除异常的情况,读者可自行分析得知。
把学生关系表分为如下两个表:

学生:(学号, 姓名, 年龄, 所在学院);
学院:(学院, 地点, 电话)


范式化和反范式化的优缺点

范式化的优点

  1. 重复数据少,不冗余。
  2. 维护更新快。
  3. 范式化的表更小,可在内存中运行。

范式化的缺点

  1. 查询的时候经常需要很多的关联,增加查询的代价。也可能使一些索引策略无效,因为范式化将列放在不同的表中,而这些列在一个表中本可以属于同一个索引。

反范式化的优点

  1. 避免关联,几乎所有数据可以在一张表中显示。
  2. 可以设计有效的索引。

反范式化的缺点

  1. 冗余数据多,更新维护麻烦,删除数据时也容易丢失重要信息。

一些建议

1. 适度冗余,减少join的关联

冗余更新频率不高,但是查询频率极高的字段。如订单中的商品名称,微博发帖中的用户昵称。

2. 大字段垂直拆分。

大字段拆分

如把博客列表中的内容拆分出去,访问列表的时候不读取博客内容,为纵深的逻辑关系。

3. 大表水平拆分

举例说明:在一个论坛系统里,管理员经常会发一些帖子,这些帖子要求在每个分类列表里都要置顶。
设计方案一:在发帖表里增加一列用来标示是否是管理员发帖,这样在每个分类列表展示时就需要对发帖表查询两次,一次是置顶帖,一次是普通帖,然后将两次结果合并。如果发帖表内容较大时,查询置顶帖的性能开销会比较大。
设计方案二:将置顶帖存放在一个单独的置顶表里。因为置顶帖数量相比会很少,但访问频率很高,这样从发帖表里分拆开来,访问的性能开销会少很多。

4. 合适的数据类型

如果数据量一样,但数据类型更小的话,数据存放同样的数据就会占用更少的空间,这样检索同样的数据所带来的IO消耗自然会降低,性能也就很自然的得到提升。此外,mysql对不同类型的数据,处理方式也不一样,比如在运算或者排序操作中,越简单的数据类型操作性能越高,所以对于要频繁进行运算或者排序的字段尽量选择简单的数据类型。


数据库表格设计原则_第4张图片
合适的数据类型

参考

  1. 阿里巴巴Java开发手册
  2. MySQL表设计原则
  3. 数据库三范式详解+例子

你可能感兴趣的:(数据库表格设计原则)