MySQL8.0实战(二) - 数据库设计

0 Github

1 简介

数据库设计(Database Design)是指对于一个给定的应用环境,构造最优的数据库模式,创建数据库及其应用系统,使之可以有效地存储数据,知足各类用户的应用需求(信息要求和处理要求)。在数据库领域内,经常把使用数据库的各种系通通称为数据库应用系统。 数据库设计的设计内容包括:需求分析、概念结构设计、逻辑结构设计、物理结构设计、数据库的实施和数据库的运行和维护。git

2 数据库建模五部曲

3 需求总结

◆ 课程的属性:{主标题,副标题,方向,分类,难度最新最热,时长,简介,人数,需知,收获,讲师名讲师职位,课程图片综合评分,内容实用,简洁易懂,逻辑清晰}github

◆ 课程列表的属性:{章名,小节名, 说明,小节时长,章节URL,视频格式}数据库

◆ 讲师的属性:{讲师昵称,说明,性别,省,市,职位说明,经验,积分,关注人数,粉丝人数}bash

◆ 问答评论属性:{类型,标题,内容,关联章节,浏览量,发布时间,用户昵称}数据库设计

◆ 笔记的属性:{用户昵称,关联章节 笔记标题,笔记内容,发布时间}。函数

◆ 用户的属性:{用户昵称密码,说明,性别,省,市,职位,说明,经验,积分,关注人数粉丝人数}性能

◆评价的属性:{用户,课程主标题,内容,综合评分,内容实用,简洁易懂,逻辑清晰,发布时间}学习

4 宽表模式

  • 百度百科定义 从字面意义上讲就是字段比较多的数据库表。一般是指业务主题相关的指标、维度、属性关联在一块儿的一张数据库表。因为把不一样的内容都放在同一张表存储,宽表已经不符合三范式的模型设计规范,随之带来的主要坏处就是数据的大量冗余,与之相对应的好处就是查询性能的提升与便捷。这种宽表的设计普遍应用于数据挖掘模型训练前的数据准备,经过把相关字段放在同一张表中,能够大大提升数据挖掘模型训练过程当中迭代计算时的效率问题。

◆ 课程的属性:{主标题,副标题,方向,分类难度最新,最热,时长,简介,人数,需知,收获,讲师名,讲师职位,课程图片综合评分,内容实用,简洁易懂,逻辑清晰}测试

  • 实例

4.1 模式存在的问题

4.1.1 更新异常

修改一行中某列的值时,同时修改了多行数据

例如当使用 优化

想修改其职位时,不止影响一条数据 那么,咱们再加个限定条件
就能够只修改一行数据,所以咱们能够将主标题做为该数据表的惟一标识,即主键! 经过主键更新数据,虽然能够避免数据的更新异常,但也可能会形成表中的数据不一致现象,好比该实例中,讲师的职称就会产生多义.

4.1.2 插入异常

部分数据因为缺失主键信息而没法写入表中

例如,咱们想新增Java开发方向的课程

因为执行该语句时,PK为空,即违反了PK非空且惟一的约束条件,所以该语句没法成功.

4.1.3 删除异常

删除某一数据时不得不删除另外一数据

例如,咱们想删除数据库方向

咱们只是单纯想删除数据库方向而已,但该语句却将许多课程也删除了,这并不符合咱们的预期.

4.1.4 数据冗余

相同的数据在一个表中出现了屡次

那么是否是这么多问题就意味着宽表一无可取呢?存在即合理!

4.2 模式的适用场景

配合列存储的数据报表应用

因为宽表中,全部数据存在于一个表中,所以在查询时,无需多表查询,SQL执行效率较高,且存在的上述问题在报表应用中都不是大问题

既然宽表不适合咱们的当前业务,那么怎么寻找合适的方法呢?

5 数据库设计范式

5.1 第一范式

表中的全部字段都是不可再分的

例如如下实例中的联系方式是一个复合属性,明显就违反了该范式,在数据库中是没法分离出来的

咱们只需对其进行简单的改动便可

即标准的二维表.

5.2 第二范式

前提

标准的二维表,即第一范式成立

表中必须存在业务主键,而且非主键依赖于所有业务主键

例如以下博客表实例

  • 使用用户字段做为PK是否可行呢? 显然一个用户会对应多个博客记录,且章节标题也能为多个用户编辑,因此单列字段PK失效

  • 使用<用户,章节,标题>的复合PK 然而用户积分字段也只和用户字段依赖,并不依赖于总体的PK,因此依旧不符合第二范式

  • 拆分将依赖的字段单独成表

从上面,咱们也能够发现:

  • 若表的PK只有一个字段组成,那么它本就符合第二范式
  • 如果多个字段组成,则需考量是否符合第二范式

5.3 第三范式

表中的非主键列之间不能相互依赖

依旧看看课程表

首先,一个字段的PK显然符合第二范式,大部分字段也只依赖于PK,然而对于讲师职称字段实际上是依赖于讲师名的,因此不符合第三范式.

  • 将不与PK造成依赖关系的字段直接提出单独成表便可

6 课程实体的逻辑建模

属性

{主标题,副标题,方向,分类,难度,最新,最热,时长,简介,人数,需知,收获,讲师名讲师职位,课程图片综合评分,内容实用,简洁易懂,逻辑清晰}

咱们显然能够将其拆分以下:

课程表

主标题(PK),副标题,方向,分类,难度,上线时间,学习人数,时长,简介,需知,收获,讲师昵称,课程图片,综合评分,内容实用,简洁易懂,逻辑清晰

讲师表

讲师名及讲师的职称

其中最新属性即对应着上线时间计算得出,业务上可规定时间段判断是否为最新 最热属性便可以学习人数字段排序来反映

课程方向表

课程方向名称(PK) : 在课程表中有对应的方向字段 添加时间

课程分类表

分类名称(PK) : 在课程表中有对应的方向字段 添加时间

课程难度表

课程难度(PK) : 在课程表中有对应的方向字段 添加时间

7 课程列表实体的逻辑建模

属性

[章节名,小节名](联合PK) 说明,小节时长,章节URL,视频格式

其中,说明其实只依赖于章节名 小节时长小节URL,视频格式都只依赖于小节名 违反第二范式,因此须要拆分字段

课程章节表

章节名(PK),说明,章节编号

课程与章节的联系表

主标题,章节名

课程小节表

小节名称(PK),小节视频url,视频格式,小节时长,小节编号

课程章节与小节的联系表

主标题,章节名,小节名

8 讲师实体的逻辑建模

属性

讲师名,密码,性别,省,市,职称,说明,经验,积分,关注数,粉丝数

讲师表

讲师名(PK),密码,性别,省,市,职称,说明,经验,积分,关注数,粉丝数

9 用户实体的逻辑建模

属性

用户昵称,密码,性别,省市,职位,说明,经验,积分,关注数,粉丝数

用户表V1.0

用户昵称(PK),密码,性别,省市,职位,说明,经验,积分,关注数,粉丝数

和讲师表基本相同,且讲师其实也是一种用户,讲师的信息就会被存储两次,形成数据的冗余.,因而就难以保持数据一致性!考虑合并!

用户表V2.0

用户昵称(PK),密码,性别,省市,职位,说明,经验,积分,关注数,粉丝数,讲师标识

10 问答评论实体的逻辑建模

属性

类型,标题,内容关联章节,浏览量,发布时间,用户昵称

其中标题文字是共享的,没法保持一致 同一用户在不一样章节提出的问题也可能相同 所以决定采用标题+用户昵称+关联章节做为PK

评论表

如何记录关联章节字段呢? 是否是只能用课程章节的PK来记录呢? 所以,不得不将课程章节的关联表PK加入

[标题,课程主标题,课程章名,小节名称,用户呢称](PK) 父评论(被回复的问题/标题) 标题,内容,类型,浏览量,发布时间

11 笔记实体的逻辑建模

属性

用户昵称,关联章节,笔记标题,笔记内容,发布时间

和评论实体差很少,分析再也不赘述

笔记表

[笔记标题,课程主标题,课程章名,小节名称,用户呢称](PK) 内容,发布时间

12 评价实体的逻辑建模

属性

用户呢称;课程主标题,内容,综合评分,内容实用,简洁易懂,逻辑清晰,发布时间

评价表

[用户呢称;课程主标题](PK) 内容,综合评分,内容实用,简洁易懂,逻辑清晰,发布时间

只有选择/购买了课程的用户才能评价!!! 须要用户与所选课程的关联关系表

用户选课表

[用户呢称;课程主标题](PK) 选课时间,累积听课时长

13 小结

14 范式化暴露的问题

若是咱们想要查询出一门课程包括全部章节和小节的相关信息

那么这些信息又是如何存储的呢,须要查询哪些表呢?以下所示

咱们就要关联5个表,查询效率极低!且查询课程信息的需求很大! 为了提升性能,咱们还须要对表结构进行优化操做

15 反范式化设计

空间换时间的思想

15.1 课程章节表反范式化设计

上述表存在一对多的关系

因此能够并不须要关联关系表,而是呢能够直接把课程表和课程&章节联系表合并

成为新的 课程章节表 [主标题,章节名](PK),说明,章节编号

虽然违反了第二范式,可是减小了一个表的查询,提升了查询性能,在频繁查询操做的系统中,这很值得!

通过反范式化后,咱们只须要查询三个表便可

15.2 反范式化设计小结

课程相关表数量 5 -> 3

16 经常使用存储引擎

17 InnoDB存储引擎的特色

  • 事务型存储引擎支持ACID
  • 数据按主键汇集存储
  • 支持行级锁及MVCC
  • 支持Btree和自适应Hash索引
  • 支持全文和空间索引

18 根据 InnoDB特性优化后的表逻辑结构

经过数据冗余避免数据不一致

课程章节表:{章节ID(PK),课程ID,章节名称,章节说明,章节编号}

课程小节表:{小节ID(PK),课程ID,章节ID,小节名称,小节视频url,视频格式,小节时长,小节编号}。

课程方向表:{课程方向ID(PK),课程方向名称,填加时间}

课程分类表:{课程分类ID(PK),分类名称,填加时间}

课程难度表:{课程难度ID(PK) ,课程难度,填加时间}

用户表:{用户ID(PK),用户昵称,密码,性别,省市,职位,说明,经验,积分,关注 人数,粉丝人数,讲师标识}

问答评论表:{评论ID(PK),父评论ID ,课程ID,章节ID,小节ID ,评论标题,用户 ID,内容,类型,浏览量,发布时间}

笔记表:{笔记ID(PK),课程ID,章节ID,小节ID笔记标题,用户呢称,笔记内容, 发布时间}

评价表:{评价ID(PK),用户ID,课程ID,内容综合评分,内容实用,简洁易懂,逻 辑清晰,发布时间}

用户选课表:{用户选课ID(PK),用户ID,课程ID,选课时间,累积听课时长}

19 经常使用的整数类型

20 经常使用的浮点类型

  • 例如:

实战实数类型的特色

  • 创建测试数据库
  • 新建表
  • 插入数据至t表中

  • 查询和
  • 和的结果
    因此只有decimal是精确的浮点类型

21 经常使用的时间类型

实战时间类型的特色

  • 新建表

  • 插入数据

  • 查询结果

  • 因为北京时间是东八区,所以咱们更改时区

  • 新的查询结果

    这就是timestamp具备时区性的特色

22 字符串类型的特色

23 如何为数据选择合适的的数据类型

23.1 优先选择符合存储数据需求的最小数据类型

INET_ATON( '255.255.255.255' ) = 4294967295
INET_ NTOA(4294967295) ='255.255.255.255'
复制代码

23.2 谨慎使用ENUM,TEXT字符串类型

23.2.1 ENUM 的迁移

数据迁移的时候,它几乎不可能被其余数据库所支持,若是 ENUM 里面是字符串,对于其余数据库来讲就更郁闷了,还不能设为tinyint等类型的字段

23.2.2 ENUM 的索引

纯数字类型的不建议用枚举类型,这是由于在 ENUM 内部维护有一个隐形的索引,也是按数字排列的,容易混淆;添加枚举值也是一个问题,若是添加在最后还好,若是添加在中间什么位置的话,原来的隐藏索引将再也不起做用

23.2.3 ENUM 字段 的NULL 值

ENUM 字段默认是能够插入 NULL 值的,这个就比较尴尬了,并且没有办法优化

23.2.4 插入的值

若是插入的值比ENUM设定的值大,会默认保存成接近的那个值;插入的值不能包含函数,不能传递参数

因此若是插入的值是数字型的,建议用tinyint,若是插入的值是字符型的,建议用char。若是真想用 ENUM 也是能够得,前提是要了解到 ENUM 的弊端,就能够有效规避这些问题

23.4 同财务相关的数值型数据,必需使用decimal类型。

24 为项目表们选择合适的数据类型

24.1 课程表

24.2 章节表

24.3 小节表

24.4 课程分类表

24.5 课程难度表

24.5 课程方向表

24.6 用户表

24.7 问答评论表

24.8 笔记表

在这里插入图片描述

24.9 用户选课表

30 如何为表和列选择合适的名字

  • 全部数据库对像名称必须使用小写字母可选用下划线分割
  • 全部数据库对像名称定义禁止使用MySQL保留关建字
  • 数据库对像的命名要能作到见名识义,而且最好不要超过32个字
  • 临时库表必须以tmp为前缀并以日期为后缀
  • 用于备份的库,表必须以bak为前缀并以日期为后缀
  • 全部存储相同数据的列名和列类型必须一致。

31 总结

工程师的必备技能

一、前奏:【业务分析】欲善其事,必三思而行; 二、高潮:【逻辑设计】范式化VS反范式化; 三、结束:【物理设计】存储引擎&数据类型&命名规约。

内容综述

  • 数据库的逻辑设计规范
  • MySQL的经常使用存储引擎及其选择方法
  • MySQL的经常使用数据类型及其选择方法
  • 如何为表选择适合的存储类型
  • 如何为表起一个好名

参考

数据库设计 MySQL慎用 ENUM 字段

更多内容请关注JavaEdge公众号

相关文章
相关标签/搜索