设计一个结构良好的数据库是需要耗费不少时间和心力的,但这是十分必要的,设计良好的数据库可以快速地查询到想要的数据并且有很好的扩展性(很容易满足新的业务需求),相反,一个设计糟糕的数据库可能需要大量维护且查询又慢又麻烦。
数据建模
- 需求分析尽可能的收集信息并分析,准确了解用户需求。
- 概念设计识别业务中的实体、事物或概念以及它们之间的关系。
- 逻辑设计抽象数据表
- 物理设计构建实体,用各种数据库软件,使用数据库技术,如事务、视图、触发器等等
- 数据库实施
- 数据库运行和维护
概念模型
表示业务中的实体、事物或概念以及它们之间的关系,无需代码。 在线画图连接draw.io (drawio.com)可以绘制下面两种来表示
E-R图
UML图
一些感想
笔者现在是一名大三学生,刚好上数据库这门课程,但是书上这一节的内容明显很垃圾,讲了一大堆E-R图的构造,手绘圆、方、菱形效率很低,很古老。 但是书上的核心思想还是在的,吐槽一下。
逻辑模型
有了概念模型后,我们需要加工出可以供数据库存储的逻辑模型。
例如,给属性选择存储类型,分析关系来决定是否要创建关系表。
概念模型只是简单的亮出了属性和关系,并没有考虑存储。 逻辑模型已经接近可以存储表信息了。
实体模型
实体模型是逻辑模型在特定DBMS上的实现,主要是一些技术上的细化,包括确定字段具体数据类型和性质(能否为空等),设置主键等
主键
- 主键就是能唯一标识表中每条记录的字段
- 尽可能不要改变
外键
MySQL里可以通过一对一或一对多两种连线表达这种先后关系/因果关系并自动建立外键,其中学生和课程被称作父表或主键表,注册事件被称作子表或外键表,外键是子表里对父表主键的引用
几个细节:
- 连线时记不得先连主表还是子表可以看状态栏的提示
- MySQL自动添加的外键会带父表前缀,没必要,建议去掉
实体模型有更多实现细节,包括设置字段具体类型和性质以及根据表间关系确定主键和外键
外键约束
有外键时,需要设置约束以防止数据损坏/污染(不一致)
- CASCADE:
瀑布/串联/级联,表示随着主键改变而改变,如主键某学生的 student_id 从1变成2,则该学生的所有注册课程记录的 student_id 也会全部变为2 (注意主键一般也最好是永远不要变的,这里讨论的是特殊情况) - RESTRICT / NO ACTION:
两者等效,作用都是禁止更改或删除主键。如:对于有过注册记录的课程,除非先删除该课程的注册购买记录,不然不能在 courses表 里删除该课程的信息 - SET NULL:
就是当主键更改或删除时,使得相应的外键变为空,这样的子表记录就没有对应的主键和对应的父表记录了(no parent),被称为孤儿记录(orphan record),这是垃圾数据,让我们不知道是谁注册的课程或不知道注册的是什么课程,一般不用,只在极其特殊的情况可能有用。
标准化
数据库规范化,又称正规化、标准化,是数据库设计的一系列原理和技术,以减少数据库中数据冗余,增进数据的一致性。
为了防止重复冗余,需要遵循数据库设计的7大规则或者说7大范式。
但是,现在数据库设计最多满足3NF,普遍认为范式过高,虽然具有对数据关系更好的约束性,但也导致数据关系表增加而令数据库IO更易繁忙,原来交由数据库处理的关系约束现更多在数据库使用程序中完成。
第三范式遵守第二范式,第二范式遵守第一范式。
第一范式
每个单元格都应该是单一值并且不能有重复的列
例如:标签有多个,也肯定很有多个记录有相同的标签,如果每个记录都记录一次就会出现重复的。 所以我们可以优化,建立一个标签表。
关系型数据库里没有多对多关系,但是可以通过一个中间表来实现多对多关系 ![[Pasted image 20231211204151.png]]
第二范式
每个表都应该是单一功能的/应该表示一个实体类型,这个表的所有字段都是用来描述这个实体的
总之,第一范式是要求单一值和无重复列,这里第二范式是要求表中所有列都只能是完全描述该表所代表的实体的属性,不属于该实体的、在记录中可重复的属性(如订单表里的顾客信息),应该另外放在描述相应实体的表里(顾客表)。
为什么第二范式好呢:
- 占用多余的储存空间。如果一个 订单表 中有 顾客名 这个字段,那同一个顾客的多个订单就会出现这个字段内容重复的情况,造成了空间浪费
- 使得修改变得困难。如果顾客修改名称,连带着所有字段都要修改。 所以应该单独建一个顾客表来储存顾客信息。
![[Pasted image 20231212153645.png]]第二范式的维基百科
第二范式(2NF)是数据库正规化所使用的正规形式。规则是要求资料表里的所有资料都要和该资料表的键(主键与候选键)有完全依赖关系:每个非键属性必须独立于任意一个候选键的任意一部分属性。如果有哪些资料只和一个键的一部分有关的话,就得把它们独立出来变成另一个资料表。(查询表)
第三范式
一个表中的字段不应该是由表中其他字段推导而来
例如,一张表有 收入 和 支出 两个字段,还有一个 盈亏总量 字段。 如果修改了前两个字段,那么必须要修改盈亏总量,否则就破坏了数据完整性,无法置信这三个字段。 所以正确的做法就是删除 盈亏总量 这个冗余字段。
第三范式的维基百科
第三范式(3NF)是数据库正规化所使用的正规形式,要求所有非主键属性都只和候选键有相关性,也就是说非主键属性之间应该是独立无关的。
如果再对第三范式做进一步加强就成了BC正规化,强调的重点在于“资料间的关系是奠基在主键上、以整个主键为考量、而且除了主键之外不考虑其他因素
模型的正向工程
通过模型正向搭建数据库:workbench 菜单的 Database 选项 → Forward Engineer 正向搭建数据库
依据向导保持默认不断点下一步就好了
数据库同步模型
修改数据库结构,比如更改某些表中字段的数据类型或增加字段之类,如果只是自己一个人用的一个本地数据库,可以直接打开对应表的设计模式并点击更改即可,但如果是在团队中工作通常不是这样。
每次需要对数据库做修改时我们需要复制相同的修改到不同的环境以保持数据的一致性
通过模型同步数据库:workbench 菜单的 Database 选项 → synchronize model 正向搭建数据库
模型的逆向工程
如果要修改没有实体模型的数据库,第一次可以先逆向工程(Reverse Engineering)建立模型,之后每次就可以在该模型上修改了
总结
设计数据库必须结合实际,尽可能地简单化问题,用最高效的办法解决。