Chap.7 数据库设计
本章针对的是更加整体性的问题, 到底怎么从头开始设计一个比较好的数据库存储结构?
我们的目标是:
- 高数据存取效率
- 高存储空间利用率
- 高系统运行管理效率
7.1 数据库设计概述
7.1.1 数据库设计特点
从数据库发展至今的规律来看, 数据库的设计通常符合这样的规律:
三分技术, 七分管理, 十二分基础数据
我们设计的过程中其实要考虑两部分: 结构 与 行为 .
结构, 通常指的是数据本身的组织结构, 即模式设计.
行为, 通常指的是数据的取用, 分析等过程.
举个例子而言, 我们上一章的模式分解, 提到大部分情况下模式分解会只到 3NF / BCNF 这一层, 这就是要考虑行为的情况, 因为 4NF 通常会导致数据过于分散, 虽然结构非常合理, 但是反而拖慢了行为的效率.
7.1.2 数据库设计的基本步骤
通常分以下六个阶段:
- 需求分析
- 信息要求
- 处理要求
- 规模要求
- 安全性 / 完整性要求
- …
- 概念结构设计
- 通常直接形成一个独立于数据库的概念模型(如 ER图 )
- 逻辑结构设计
- 转化为关系模型, 并对其进行优化(比如模式分解)
- 物理结构设计
- 存储结构
- 管理方法等
- 这一步通常可以交由数据库系统自行完成
- 数据库实施
- 使用SQL或者更新的数据库框架(SpringBoot等)编写数据库原码
- 组织数据入库
- 试运行
- 数据库运行及维护
- 后续的运维
接下来应该会一个个讲.
7.2 需求分析
需求分析的任务其实就是要 系统地, 明确的了解用户的要求.
其重点应当放在:
- 信息要求
- 处理要求
- 安全性与完整性要求
这三个方面.
这一阶段的重要目标是形成需求说明书, 并初步确定数据字典(不知道读者还记不记得这个玩意, 定义附在下面).
我们把数据字典拿出来单聊一下, 这个玩意包括数据库中各种各样的定义:
- 数据项
- 名字(学号)
- 含义(唯一标识每个学生)
- 别名(学生编号)
- 数据类型(字符型)
- 长度(8)
- 取值范围(00000000至99999999)
- 取值含义(前两位是学生所在年级, 后几位按顺序编号)
- 与其他数据项的逻辑关系
- 数据结构
- 数据结构名(学生)
- 含义说明(是学籍管理中的主体数据结构)
- 组成(学号, 姓名, 性别, 年龄, 所在系)
- 数据流
- 数据流名: 开课列表
- 说明: 选课阶段开启的可选课程
- 来源: 课程表
- 去向: 可选课表
- 组成
- 平均流量: 单位时间的传输次数
- 高峰期流量: 高峰时期的数据流量
- 数据存储
- 数据存储名: 学生登记表
- 说明
- 流入数据流
- 流出数据流
- 组成
- 数据量: 每年3000张
- 存取方式: 随机存取
- 处理过程
- 处理过程名: 分配选课结果
- 说明
- 输入: 学生, 选课记录
- 输出: 选课安排
- 处理细节
7.3 概念结构设计
概念结构设计其实我们很熟悉, 就是将现实世界中的实体和关系转化成有组织的ER图.
拿出这张图:
当然, ER图也有实体的层次, 比如学院是一个实体, 学生又是另一个实体. 怎么按部就班的设计是一个问题. 通常而言, 有这四种方式:
- 自顶向下: 从最大, 最全局的概念开始设计起, 逐步扩展到下级细节概念
- 自底向上: 就是上面这个过程反过来, 从细节往上推导
- 逐步扩张: 以需求为中心, 逐步扩张出其它的概念模型
- 混合模型: 自顶向下的探讨需求, 在针对每个细节需求自底向上地给出概念模型.
注意
ER图设计的原则是能用属性表示的, 都不用实体.
当然, 也要符合我们之前说的属性不能再分的特点, 你不能说学生硬当成一个属性来看待对吧.
经过以上过程后, 我们应该会得到很多ER图, 随后只需要将他们集成起来即可:
- 解决冲突 / 合并: 解决不同图之间的冲突部分.
- 属性冲突: 比如相同含义的属性在不同的图中有不同的取值范围 / 甚至不同的数据结构
- 命名冲突: 同名异义, 或者同义异名
- 结构冲突: 同一个对象在不同的应用中的抽象不同等
- 修改 / 重构: 消除不必要的冗余
- 就是一些能从别的基本表中推导出的数据, 就把它去掉.(也要看具体情况, 如果能沟通大幅提高查询效率, 也可以不去掉, 而是使用冗余数据方式来增加效率)
- 验证整体概念结构
7.4 逻辑结构设计
逻辑结构设计的目标是将设计好的ER图转化成选用数据库系统支持的数据模型与逻辑结构.
7.4.1 ER图到关系模型
我们知道ER图中有三种关系:
- 一对一
- 一对多
- 多对多
对于 一对一 , 通常可以直接将一个实体转化成另一个实体的一个外键.
对于 一对多 , 通常也可以直接在n段的实体的关系模型上多加一个外键.
对于 多对多 , 就得单独转成一个具体的关系模式(表)了.
7.4.2 数据模型的优化
这玩意说白了就是我们上一章提到的 规范化 , 就是到3NF / BCNF的那个东西.
7.4.3 设计用户子模式
用户子模式其实主要是针对 外模式 这一层而言的.
这一阶段的设计要考虑到用户的使用习惯, 比如针对不同的用户定义不同的视图等等.
7.5 物理结构设计
这一部分着重于系统内信息的存储结构和方法, 其实一般而言, 如果数据库规模不算很大, 可以交由数据库自行处理.
7.5.1 数据库物理设计的内容和方法
对于关系数据库主要就两个内容:
- 为关系模式选择存取方法(存储路径的选择)
- 设计关系 / 索引的物理存储结构
7.5.2 关系模式存取方法的选择
常用的存取方法有三种:
- B+树索引
- Hash索引
- 聚簇索引
这个东西我们在第三章提过一嘴, 只需要明确聚簇索引只能建立一个就行了. 前两个其实只要知道 B+ 树 / Hash 是什么, 应该好理解.
7.5.3 设计数据库的存储结构
设计具体的存储结构时, 有几个很通用的规则:
- 容易变化的部分和稳定的部分分开存放
- 经常读取的部分和存取频率低的部分分开放
数据库通常会对存储参数设定一个合理的基本值.
至于自定义这些基本值, 或者更改存储方式, 属于比较深的内容了, 本博客在这里不涉及.
本章看起来分点很多, 但是实际上大部分工作数据库管理系统都能为你自动完成.
比较重要的部分就是如何将现实中的关系转化为ER图, 以及如何将ER图进一步转成关系模式.