极简数据库设计

1,324 阅读6分钟

什么是数据库设计?

数据库设计是指根据业务的需要,建立最适合的存储模型,使之能有效的存储和高效的访问。

优秀的设计可以让数据的存储和访问变得更加优雅。

好的设计 坏的设计
减少冗余 大量冗余
维护简单 易产生异常
节约 浪费
高效 低效

设计的步骤

如图所示,通常数据库设计分为:需求分析,逻辑设计,物理设计,维护优化。

数据库设计步骤

接下来,我们会对这四个步骤依次讲解。

需求分析

在进行需求分析的时候,我们需要了解所要存储的数据,及其存储特点和生命周期。

为此,我们需要搞清楚:

  1. 实体与实体之间的关系(1对1,1对多,多对多)
  2. 实体所包含的属性
  3. 哪些属性或属性的组合可以唯一标识一个实体。

逻辑设计

逻辑设计是指将需求转化为数据库的逻辑模型,通过 ER 图的形式对逻辑模型进行展示。它与所选用的具体的 DBMS 系统无关。

ER 图

ER 图例说明

ER图

下面是一个简单的电商网站 ER 图示例

电商网站ER图

设计范式

上面电商网站示例中,用户信息和购物车信息是存在一张表中,还是单独存放?这就涉及到设计范式

常见的数据库设计范式包括:

  • 第一范式
  • 第二范式
  • 第三范式
  • 以及 BC 范式

当然还有第四范式,第五范式。不过在这里我们会把重点放到前三个范式上,这也是大多数数据库设计所要遵循的范式。

遵循这些设计范式,将会极大地减少数据操作异常和冗余。

第一范式(1NF)

🌟 数据库表中的所有字段都是单一属性,不可再分。

换句话说,第一范式要求数据库中的表都是二维表。

第一范式

幸运的是,大多数的数据库系统都满足第一范式。

第二范式(2NF)

🌟 表中必须存在业务主键,并且非主键依赖于全部业务主键。

单关键字段的表都满足第二范式。

如下表,商品名称供应商唯一决定了一条记录,是复合主键。

其中价格依赖于商品名称供应商,但是供应商电话只依赖于供应商分类只依赖于商品名称。故该表不满足第二范式。

可以对其拆分,使其满足第二范式。

第二范式

第三范式(3NF)

🌟 表中的非主键列之间不能相互依赖或者传递依赖。

下表中,商品名称是主键列,分类描述依赖于分类分类依赖于商品名称,则分类描述传递依赖于商品名称。故不满足第三范式。

可以对其拆分,使其满足第三范式。

第三范式

BC范式(BCNF)

🌟 表中复合关键字之间也不能相互依赖。

物理设计

在物理设计阶段,我们首先要选择合适的数据库管理系统,如 Oracle、SQL Server、MySQL,PostgreSQL 等。接下来我们要定义数据库、表及字段的命名规范,然后根据所选的 DBMS 系统选择合适的字段类型。

选择数据库

根据预算及项目的特点选择合适的数据库。

商业数据库价格不菲,适合企业级的项目开发,比如业界口碑较好的 Oracle 。对于普通互联网公司使用免费开源的数据库是一种更好地选择,比如 MySQL 。

同时,还要考虑项目的具体应用场景,对于一些需要频繁使用事务操作的项目,如电商、银行、火车订票系统等,使用某些商业数据库会更好,因为在这些数据库中,事务操作的成本会更低。

另一方面,还要考虑使用的操作系统和编程语言。如 .NET 开发搭配 Windows Server 操作系统和 SQLServer 数据库会更方便。

常见数据库

表及字段的命名规则

对象命名应遵循以下规则:

  1. 可读性原则。使用大小写或下划线来获得更好地可读性。
  2. 表意性原则。对象的名字应该能直观的描述该对象的含义。
  3. 长名原则。少使用缩写,多使用全名以消除歧义。不要使用拼音。

命名规范

字段类型选择的原则

★ 优先选择数字类型,而不是字符串类型。

★ 对于相同数据类型,优先选择可用的存储空间最小的类型。如在 MySQL 中,能使用tinyint,就不要使用int

以上的选择原则主要从以下两个方面考虑:

  1. 数据比较的时候,字符处理往往比数字慢。
  2. 数据从外存调入内存,列的数据长度越小,单次调入的数据总量就越多,越利于性能的提升。

反范式化

前面我们说了第三范式:表中的非主键列之间不能相互依赖或者传递依赖。

反范式化就是为了性能和读取效率,而适当的违反第三范式,允许存在少量的数据冗余。

有时候完全遵循第三范式,会导致频繁的表关联,反而使得查询效率降低。

即使用空间来换时间的策略。

反范式化要适度

维护和优化

要做什么?

  1. 维护数据字典(如将性别字段的01所代表的含义记录在个人数据字典中)
  2. 维护索引
  3. 维护表结构
  4. 适当对表进行拆分

维护数据字典

我们可以使用数据库本身的备注字段来维护数据字典。

以 MySQL 为例:

CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增 ID',
  `name` varchar(50) NOT NULL COMMENT '用户名',
  `gender` tinyint(1) DEFAULT 0 COMMENT '用户性别,0表示男,1表示女',
  PRIMARY KEY (`id`)
);

则使用以下方式导出数据字典:

SELECT
	TABLE_NAME,-- 表名
	COLUMN_COMMENT,-- 列注释
	COLUMN_NAME,-- 列名
	COLUMN_TYPE -- 列的数据类型
FROM
	information_schema.COLUMNS 
WHERE
	TABLE_NAME = 'users'

得到

数据字典

维护索引

如何选择合适的列建立索引?

  1. 出现在WHERE语句,GROUP BY从句,ORDER BY从句中的列
  2. 可选择性高的列要放到索引的前面
  3. 索引中不要包括太长的数据类型

索引不是越多越好,过多的索引会降低读写的效率。

维护表结构

维护什么?

  1. 对表本身的字段进行维护
  2. 对字典进行维护
  3. 控制表的宽度和大小

适当对表进行拆分

对宽表进行垂直拆分

将经常一起查询的列拆分到一个表中。对于text、blob等大字段拆分到附加表中。

垂直拆分

对长表进行水平拆分

可以通过对主键取哈希值,将一个大表水平拆分成若干小表。

水平拆分


That's all.