数据库设计(Database Design)是指对于一个给定的应用环境,构造最优的数据库模式,建立数据库及其应用系统,使之能够有效地存储数据,满足各种用户的应用需求(信息要求和处理要求)。在数据库领域内,常常把使用数据库的各类系统统称为数据库应用系统。
数据库设计的设计内容包括:需求分析、概念结构设计、逻辑结构设计、物理结构设计、数据库的实施和数据库的运行和维护。
◆ 课程的属性:{主标题,副标题,方向,分类,难度最新最热,时长,简介,人数,需知,收获,讲师名讲师职位,课程图片综合评分,内容实用,简洁易懂,逻辑清晰}
◆ 课程列表的属性:{章名,小节名, 说明,小节时长,章节URL,视频格式}
◆ 讲师的属性:{讲师昵称,说明,性别,省,市,职位说明,经验,积分,关注人数,粉丝人数}
◆ 问答评论属性:{类型,标题,内容,关联章节,浏览量,发布时间,用户昵称}
◆ 笔记的属性:{用户昵称,关联章节 笔记标题,笔记内容,发布时间}。
◆ 用户的属性:{用户昵称密码,说明,性别,省,市,职位,说明,经验,积分,关注人数粉丝人数}
◆评价的属性:{用户,课程主标题,内容,综合评分,内容实用,简洁易懂,逻辑清晰,发布时间}
◆ 课程的属性:{主标题,副标题,方向,分类难度最新,最热,时长,简介,人数,需知,收获,讲师名,讲师职位,课程图片综合评分,内容实用,简洁易懂,逻辑清晰}
例如当使用
想修改其职位时,不止影响一条数据
那么,我们再加个限定条件
就可以只修改一行数据,因此我们可以将主标题作为该数据表的唯一标识,即主键!
通过主键更新数据,虽然可以避免数据的更新异常,但也可能会造成表中的数据不一致现象,比如该实例中,讲师的职称就会产生多义.
例如,我们想新增Java开发方向的课程
由于执行该语句时,PK为空,即违反了PK非空且唯一的约束条件,因此该语句无法成功.
例如,我们想删除数据库方向
我们只是单纯想删除数据库方向而已,但该语句却将许多课程也删除了,这并不符合我们的预期.
相同的数据在一个表中出现了多次
那么是不是这么多问题就意味着宽表一无是处呢?存在即合理!
由于宽表中,所有数据存在于一个表中,因此在查询时,无需多表查询,SQL执行效率较高,且存在的上述问题在报表应用中都不是大问题
既然宽表不适合我们的当前业务,那么怎么寻找合适的方法呢?
例如以下实例中的联系方式是一个复合属性,明显就违反了该范式,在数据库中是无法分离出来的
我们只需对其进行简单的改动即可
即标准的二维表.
前提
标准的二维表,即第一范式成立
表中必须存在业务主键,并且非主键依赖于全部
业务主键
例如如下博客表实例
从上面,我们也可以发现:
依旧看看课程表
首先,一个字段的PK显然符合第二范式,大部分字段也只依赖于PK,然而对于讲师职称字段其实是依赖于讲师名的,所以不符合第三范式.
{主标题,副标题,方向,分类,难度,最新,最热,时长,简介,人数,需知,收获,讲师名讲师职位,课程图片综合评分,内容实用,简洁易懂,逻辑清晰}
我们显然可以将其拆分如下:
主标题(PK)
,副标题,方向,分类,难度,上线时间,学习人数,时长,简介,需知,收获,讲师昵称,课程图片,综合评分,内容实用,简洁易懂,逻辑清晰
讲师名及讲师的职称
其中最新
属性即对应着上线时间计算得出,业务上可规定时间段判断是否为最新
最热
属性即可以学习人数字段排序来反映
课程方向名称(PK)
: 在课程表中有对应的方向字段
添加时间
分类名称(PK)
: 在课程表中有对应的方向字段
添加时间
课程难度(PK)
: 在课程表中有对应的方向字段
添加时间
章节名,小节名(联合PK)
说明,小节时长,章节URL,视频格式
其中,说明
其实只依赖于章节名
小节时长
,小节URL
,视频格式
都只依赖于小节名
违反第二范式,所以需要拆分字段
章节名(PK)
,说明,章节编号
主标题,章节名
小节名称(PK),小节视频url,视频格式,小节时长,小节编号
主标题,章节名,小节名
讲师名,密码,性别,省,市,职称,说明,经验,积分,关注数,粉丝数
讲师名(PK)
,密码,性别,省,市,职称,说明,经验,积分,关注数,粉丝数
用户昵称,密码,性别,省市,职位,说明,经验,积分,关注数,粉丝数
用户昵称(PK)
,密码,性别,省市,职位,说明,经验,积分,关注数,粉丝数
和讲师表基本相同,且讲师其实也是一种用户,讲师的信息就会被存储两次,造成数据的冗余.,于是就难以保持数据一致性!考虑合并!
用户昵称(PK)
,密码,性别,省市,职位,说明,经验,积分,关注数,粉丝数,讲师标识
类型,标题,内容关联章节,浏览量,发布时间,用户昵称
其中标题文字是共享的,无法保持一致
同一用户在不同章节提出的问题也可能相同
因此决定采用标题+用户昵称+关联章节
作为PK
如何记录关联章节字段呢?
是不是只能用课程章节的PK来记录呢?
因此,不得不将课程章节的关联表PK加入
[标题,课程主标题,课程章名,小节名称,用户呢称](PK)
父评论(被回复的问题/标题)
标题,内容,类型,浏览量,发布时间
用户昵称,关联章节,笔记标题,笔记内容,发布时间
和评论实体差不多,分析不再赘述
[笔记标题,课程主标题,课程章名,小节名称,用户呢称](PK)
内容,发布时间
用户呢称;课程主标题,内容,综合评分,内容实用,简洁易懂,逻辑清晰,发布时间
[用户呢称;课程主标题](PK)
内容,综合评分,内容实用,简洁易懂,逻辑清晰,发布时间
只有选择/购买了课程的用户才能评价!!! 需要用户与所选课程的关联关系表
[用户呢称;课程主标题](PK)
选课时间,累积听课时长
如果我们想要查询出一门课程包括所有章节和小节的相关信息
那么这些信息又是如何存储的呢,需要查询哪些表呢?如下所示
我们就要关联5个表,查询效率极低!且查询课程信息的需求很大!
为了提高性能,我们还需要对表结构进行优化操作
空间换时间的思想
上述表存在一对多的关系
所以可以并不需要关联关系表,而是呢可以直接把课程表和课程&章节联系表合并
成为新的课程章节表
[主标题,章节名](PK)
,说明,章节编号
虽然违反了第二范式,但是减少了一个表的查询,提高了查询性能,在频繁查询操作的系统中,这很值得!
经过反范式化后,我们只需要查询三个表即可
课程相关表数量 5 -> 3
通过数据冗余避免数据不一致
课程章节表:{章节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,选课时间,累积听课时长}
这就是timestamp具有时区性的特点
22 字符串类型的特点INET_ATON( '255.255.255.255' ) = 4294967295
INET_ NTOA(4294967295) ='255.255.255.255'
数据迁移的时候,它几乎不可能被其他数据库所支持,如果 ENUM 里面是字符串,对于其他数据库来说就更郁闷了,还不能设为tinyint等类型的字段
纯数字类型的不建议用枚举类型,这是因为在 ENUM 内部维护有一个隐形的索引,也是按数字排列的,容易混淆;添加枚举值也是一个问题,如果添加在最后还好,如果添加在中间什么位置的话,原来的隐藏索引将不再起作用
ENUM 字段默认是可以插入 NULL 值的,这个就比较尴尬了,而且没有办法优化
如果插入的值比ENUM设定的值大,会默认保存成接近的那个值;插入的值不能包含函数,不能传递参数
所以如果插入的值是数字型的,建议用tinyint,如果插入的值是字符型的,建议用char。如果真想用 ENUM 也是可以得,前提是要了解到 ENUM 的弊端,就可以有效规避这些问题
1、前奏:【业务分析】欲善其事,必三思而行;
2、高潮:【逻辑设计】范式化VS反范式化;
3、结束:【物理设计】存储引擎&数据类型&命名规约。
更多内容请关注JavaEdge公众号
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。