数据结构设计的目的:
示例表:记录每个学生所选课程信息,学号 课程名为主键
1、减少数据冗余,相同的不必要的数据在多个地方存在
如表中,多次出现学生姓名跟生日信息,课程学分都是冗余的
2、尽量避免数据维护中出现更新,插入和删除异常
- 插入异常:如果表中的某个实体随着另一个实体而存在,如表中需要插入一门课程,但是没有学生选择这门课,那么单独插入课程名及课程其信息是会报错的。
- 更新异常:如果更改表中的某个实体的单独属性时,需要对多行进行更新。如表中,需要更新数学这门课程的学分,会同时更新两行,随着选择课程的学生变多,也会造成更多记录的更新。
- 删除异常:如果删除表中的某一实体则会导致其他实体的消失。如表中,删除数学课程,会删除多条记录
3、节约数据存储空间
4、提高查询效率
数据库结构设计步骤:
- 需求分析:全面了解产品设计的存储需求、数据处理需求、数据的安全性和完整性
- 逻辑设计:设计数据的逻辑存储结构、数据实体之间的逻辑关系,解决数据冗余和数据维护异常
- 物理设计:根据所使用的的数据库特点进行表结构设计
- 维护优化:根据实际情况对索引、存储结构等进行优化
数据库设计范式:
- 第一范式:数据库表中的所有字段都只具有单一属性,每一列都由基本的数据类型所构成,设计出来的表都是简单的二维表。
- 第二范式:要求一个表中只具有一个业务主键,不能存在非主键列对部分主键的依赖关系。如表中主键学号 课程名,但学分与学号无直接依赖关系,所以只对课程名有依赖关系,不满足第二范式。修改:单独列一个学生信息表和课程信息表,选课表只需要关注学号与课程名的信息即可
- 第三范式:每一个非主属性既不部分依赖也不传递依赖于业务主键,即在第二范式的基础上消除了非主属性对主键的传递依赖。
如下表:学生信息表
学号可以确定学生所在学院,那么学院信息又跟学生信息有了依赖关系,这就违反了第三范式。那么将学生信息表中只保留学院名称,单独创建一个学院信息表,存放学院信息,主键为学院名称。这样的话两张表就符合了第三范式需求。
反范式化:
使用空间换取时间,为了性能和读取效率的考虑适当的对数据库设计范式的要求进行违反,允许存在少量的数据冗余
范式化设计的优缺点:
优点:可以尽量减少数据冗余、范式化的更新操作比反范式化快、范式化的表通常比反范式化更小
缺点:对于查询需要关联多个表、更难进行索引优化
反范式化设计优缺点:
优点:可以减少表的关联、可以更好的进行索引优化
缺点:存在数据冗余及数据维护异常、对数据的修改需要更多的成本
物理设计:
根据所选择的关系型数据库的特点对逻辑模型进行存储结构设计
内容:定义数据库、表及字段的命名规范:遵循可读性、表意性、长名性原则
选择合适的存储引擎:根据各引擎的适用性,根据场景选择合适的存储引擎
为表中的字段选择合适的数据类型:当一个列可以选择多种数据类型时,应该优先考虑数字类型,其次是日期或二进制类型,最后是字符类型。对于相同级别的数据类型,应该优先选择占用空间小的数据类型
实数类型比较:
- FLOAT占4个字节,不是精确类型
- DOUBLE占8个字节,不是精确类型
- DECIMAL每4个字节存9个数字,小数点占一个字节。如:DECIMAL(18,9)需要9个字节来存储
VARCHAR和CHAR类型:
VARCHAR和CHAR存储空间是按字符并不是字节
VARCHAR类型的存储特点:
- varchar用于存储变长字符串,只占用必要的存储空间
- 列的最大长度小于255则只占用一个额外字节用于记录字符串长度
- 列的最大长度大于255则要占用两个额外字节用于记录字符串长度
VARCHAR长度选择问题:
尽可能使用最小的符合需求的长度
varchar(5)和varchar(200)对于数据库来说是根据实际数据长度去分配内存,但MySQL在内存中对字符的使用是固定宽度,列宽度太长会消耗更多的内存。
VARCHAR适用场景:
- 字符串列的最大长度比平均长度大很多
- 字符串列很少被更新
- 使用了多字节字符集存储字符串
CHAR类型的存储特点:
- CHAR类型是定长的
- 字符串存储在CHAR类型的列中会删除末尾的空格
- CHAR类型的最大宽度为255
CHAR类型的适用场景:
- CHAR类型适合存储所长度近似的值
- CHAR类型适合存储短字符串
- CHAR类型适合存储经常更新的字符串列
日期数据类型:
DATATIME:
以YYYY-MM-DD HH:MM:SS[fraction]格式存储日期时间。DATATIME类型与时区无关,占用8个字节的存储空间。时间范围1000-01-01 00:00:00到9999-12-31 23:59:59
datetime = YYYY-MM-DD HH:MM:SS
datetime(6) = YYYY-MM-DD HH:MM:SS.fraction
TIMESTAMP:
依赖于所指定的时区,在行的数据修改时可以自动修改timestamp列的值
date和time:
date类型用于保存1000-01-01到9999-12-31之间的日期
time类型用于存储时间数据,格式为HH:MM:SS
date类型的优点:
- 占用的字节数比使用字符串、datetime, int存储要少,使用date类型只需要3个字节
- 使用Date类型还可以利用日期时间函数进行日期之间的计算
存储日期时间数据的注意事项:
- 不要使用字符串类型来存储日期时间数据
- 日期时间类型通常比字符串占用的存储空间小日期时间类型在进行查找过滤时可以利用日期来进行对比
- 日期时间类型还有着丰富的处理函数,可以方便的对时期类型进行日期计算
参考文献:
- 高性能MySQL第三版
- 扛得住的MySQL数据库架构:https://coding.imooc.com/class/chapter/49.html#Anchor