温习:数据库设计是什么?三大范式怎么玩?如何设计ER关系图?

温习一下关系型数据库设计,其中最重要的就是理解三大范式,至于ER图,如果心中有谱,画在纸上也成。在网上找到一遍实用的文章,见:https://my.oschina.net/u/4414412/blog/3257987。内容部分摘录如下:

数据库设计是什么?

数据库设计是根据需求文档的描述,将需求转成数据库的存储结构的过程。

数据库设计要尽量符合数据库设计的三大范式原则——目标是解决数据的冗余问题

什么又是冗余?我从知乎上找了个示例:全文见:https://www.zhihu.com/question/24696366/answer/29189700

数据冗余表格例子

如上:你会看到好多个“王强”,好多个“经济系”,这样很多重复的数据,这就称之为冗余。而以下要学习的范式,就是要解决上述存在的问题。

(关系模式设计中可能会出现以下几个问题:数据冗余、数据修改不一致、数据插入异常、数据删除异常,所以提出范式的要求,目的就是最低限度地冗余,避免插入、删除、修改异常。)

遵循“三大范式”规则(良好示例)

说明:为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范式是符合某一种设计要求的总结。要想设计一个结构合理的关系型数据库,必须满足一定的范式。

第一范式 (确保每列保持原子性)

第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。

第一范式的合理遵循需要根据系统的实际需求来定。比如某些数据库系统中需要用到 “地址” 这个属性,本来直接将 “地址” 属性设计成一个数据库表的字段就行。但是如果系统经常会访问 “地址” 属性中的 “城市” 部分,那么就非要将 “地址” 这个属性重新拆分为省份、城市、详细地址等多个部分进行存储,这样在对地址中某一部分操作的时候将非常方便。这样设计才算满足了数据库的第一范式,如下表所示。

上表所示的用户信息遵循了第一范式的要求,这样在对用户使用城市进行分类的时候就非常方便,也提高了数据库的性能。

第二范式 (确保表中的每列都和主键相关)

非主键列必须依赖主键列存在。

第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中

比如要设计一个订单信息表,因为订单中可能会有多种商品,所以要将订单编号和商品编号作为数据库表的联合主键,如下表所示。

 订单信息表

这样就产生一个问题:这个表中是以订单编号和商品编号作为联合主键。这样在该表中商品名称、单位、商品价格等信息不与该表的主键相关,而仅仅是与商品编号相关。所以在这里违反了第二范式的设计原则。

而如果把这个订单信息表进行拆分,把商品信息分离到另一个表中,把订单项目表也分离到另一个表中,就非常完美了。如下所示。

这样设计,在很大程度上减小了数据库的冗余。如果要获取订单的商品信息,使用商品编号到商品信息表中查询即可。

第三范式 (确保每列都和主键列直接相关,而不是间接相关 - 在 2NF 基础上消除传递依赖)

第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。如下面这两个表所示的设计就是一个满足第三范式的数据库表。

这样在查询订单信息的时候,就可以使用客户编号来引用客户信息表中的记录,也不必在订单信息表中多次输入客户信息的内容,减小了数据冗余。

三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求 > 性能 > 表结构(范式)。所以不能一味的去追求范式建立数据库。

示例:冗余数据与需求/性能的平衡

如上,在数据库设计中,遵循范式,目的就是为了避免数据的冗余,但是在实际的数据库设计中,并不完全一定要按三大范式去执行,而是追求一种平衡,这要如何理解呢?此文有举例如下:

性能的要求出现的冗余数据

很多系统都要记录日志。而日志里面,必须要包括用户的信息。如果严格按照三大方式。日志的用户信息必须是从用户表中获得,日志每天都会出现巨量的数据。如果关联用户表查询,整理日志时会导致用户表的访问大大被拖慢(理解补充:导致性能下降)。

所以,我们会将用户的信息直接写在日志表里面。在日志表中写用户的的信息,明显违反了第二范式,基于查询的性能的需要,一般日志表的用户信息是冗余。

(理解补充:满足需求优先)

示例:业务逻辑的要求出现的冗余数据

我们在订单中有一个商品的价格、商品名字。而这个商品的价格直接就是订单的字段。并不是商品表里面商品的价格。明显违反了第三范式.

但业务上,由于订单的商品价格不能随着商家修改了商品价格而修改。所以像这种需求下,必须要给订单表一个冗余的商品价格字段。

(理解补充:满足业务逻辑优先。例如我在京东上买东西,可以查看三个月或更长时间的订单信息,因此订单的商品价格,应当是下单时那个价格,而不是随着时间变化,有调整的商品价格。)

(我发现这两个示例,较适合后台管理,是针对已经发生的行为做的数据记录,便于管理者/用户查询之用,也方便删除,这些操作不会影响其他的表(如商品表,大量在前台展示/访问),这种冗余设计是很有意义的。因此,在数据库的设计上,大的宏观/顶层方面,是要遵守范式,在此之内,则具体情况具体对待。)

再次摘录:

三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求 > 性能 > 表结构(范式)。所以不能一味的去追求范式建立数据库。

这就是数据库设计,宏观层面的指导原则。

由需求确定的数据库表与表的从属关系

表与表之间的关系包括有:一对一、一对多/多对一、多对多。

关系数据库是不能直接支持多对多的业务关系的,如果出现多对多必须要拆分一个中间表(见下面的示例表),原因是数据库里面的字段不能存储一个集合数据。

没有一丝丝愧疚

(这个图,似乎点儿多对多的意思~但细品,却不是这样。)

数据库表与表的关系,就是也需求描述的从属关系。是由需求决定的。先确定需求,再讨论表之间的关系。

示例:

遵循范式设计:

(严格按照范式,设计成三个表,多对多关系——其中第三个表存储第一和第二个表之间的关系。)

以实际需求为主的设计:

      

(按实际需求,设计成两个表,看上去是一对多关系,然本质上还是多对多,只是teacher_id这个对应的外键字段,存储了多个值。我发现这是一个值得学习的技巧和良好示例,因为获取数据可用SQL语句的select结合in来解决。)

文章中的总结:

为什么需要三大范式,避免数据的冗余,导致数据的异常。

数据库设计总体上要符合三大范式,但是基于业务需求和性能要求,有时候可以有少许的冗余。数据设计冗余,设计者必须要说明原因 (项目需求需要)

ER数据库关系图的设计与示例

数据库设计的流程上,我们通常根据需求,画出数据的 ER 图(Entity Relational)。然后在通过 ER 图生成数据库的建库脚本。

ER 图,所谓的 ER 图就是数据库关系图。

进一步,数据库设计,就是通过 ER 图,根据需求给数据库建立表结构!

示例1——需求:设计一个学生成绩管理系统

  1. 首先有学生,学生必须包括登录、禁用功能
  2. 基于安全性的考虑,学生的身份信息要单独存储
  3. 一个学生有多门成绩
  4. 一个学生可以有多个老师,一个老师也可以教多个学生

第一步:标识表,标识实体表。学生、学生身份、成绩、老师

第二步:标识字段

第三步:标识表与表之间的关系

用ER设计图来表示,如下:

示例2——CRM 系统的数据库设计

客户调研

客户人员是一个不懂软件设计的人,它希望有一个可以做管理系统来管理他的员工。

描述如下:

系统的需求调研:

1. 每个销售人员只能查看自己的客户. (销售不能互相看客户)

2. 客户是公司,有多个联系人  (客户主体公司)

3. 销售可以指定客户给另一个销售人员跟进 (销售人员可以转移客户给另外销售)

4. 销售人员离职时,可以禁用不让登录

5. 管理员可以修改销售人员的密码 (后台管理人员可以管理所有信息)

6. 销售人员可以设置重点跟进客户,并且可以说明重点跟进客户的原因.

7. 销售人员可以多次跟进同一个客户(骚扰)

系统功能列表(需求文档的核心部分)

功能列表给到客户人员。给到开发人员,跟进需求文档设计数据库。

前端功能(销售人员的功能)1. 客户管理
2. 联系人管理
3. 转移客户
4. 跟进客户
5. 标记重点客户
后台管理(管理员管理 RBAC)1. 客户管理 (全局)
2. 联系人管理(全局)
3. 管理员管理
4. 角色管理
5. 权限管理

(需求排第一)

数据库设计

根据功能列表与客户调研报告(需求文档),设计数据数据库。

第一步:RBAC 系统的设计

Role Based Access Control (基于角色的权限控制系统);就是根据不同的用户,根据用于所属的角色不同而登录的界面就不同。

需求:一个管理员只有一个角色(单角色的设计),一个角色可以有多个管理员。

一个就是可以有多个权限,一个权限也可以有在多个角色角色。

(理解补充:RBAC系统是通用的模块。例如很多年前的ASP.NET,就自带有此功能,最近接触django,也是默认就提供这样的后台管理功能。)

第二步:业务系统的设计(CRM)

需求:

  1. 一个销售(用户),只能查看自己的客户
  2. 客户是公司,有多个联系人  (客户主体公司)
  3. 销售人员可以设置重点跟进客户,并且可以说明重点跟进客户的原因.
  4. 销售人员离职时,可以禁用不让登录
  5. 销售人员可以多次跟进同一个客户(骚扰)
  6. 销售可以指定客户给另一个销售人员跟进

数据设计工具与软件

文章示例是用PowerDesigner专业软件,可以制作ER图和导出sql来直接创建数据结构。

但我似乎用不着这么专业的软件,只是要画ER图的话,我用ProcessOn就好。

全文参见:https://my.oschina.net/u/4414412/blog/3257987

相关文章

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注