MySQL数据库设计思想
一.数据库设计的目的
主要是为了减少数据冗余,避免数据维护异常,节省空间,高效访问。
二.数据库设计的思想
1.理论
a.范式的概念
第一范式: 数据表中所有字段都是单一属性,不可再分
第二范式: 在第一范式的基础上,数据表中不存在非关键字段对任意候选关键字段的部分函数依赖
注:部分函数依赖是指,存在组合关键字中的某一关键字决定非关键字的情况,所有的单关键字都符合第二范式
第三范式: 在第二范式的基础上,数据表中不存在非关键字段,对任意候选关键字段的传递依赖
BC范式:在第三范式的基础上,数据表中不存在任何字段对任一候选关键字段的传递依赖
注:也就是说如果是复合关键字,则复合关键字之间不能存在函数依赖关系
b.异常和冗余
1.插入异常 如果某个实体随着另一个实体的存在而存在,即缺少某个实体时无法表示这个实体,那么这个表就存在插入异常
2.更新异常 如果更改表所对应的某个实体实例的单独属性时,需要将多行更新,那么就说这个表存在更新异常
3.删除异常 如果删除表的某一行来反映某实体实例,失效时导致另一个不同 实体实例信息丢失,那么这个表就存在删除异常
4.数据冗余 是指相同的数据在多个地方存在,或者说表中的某个列可以由其他列计算得到,这样就说表中存在数据冗余
2.物理设计
- 考虑常见的存储引擎
存储引擎 | 事物 | 锁粒度 | 主要应用 | 忌用 |
---|---|---|---|---|
MyISIM | 不支持 | 支持并发插入的表级锁 | select insert | 读写操作频繁 |
MRG_MyISIM | 不支持 | 支持并发插入的表级锁 | 分段归档,数据仓库 | 全局查找过多的场景 |
Innodb | 支持 | 支持MVCC的行级锁 | 事物处理 | 无 |
Archive | 不支持 | 行级锁 | 日志记录只支持insert select | 需要随机读取更新删除 |
Ndb cluster | 支持 | 行级锁 | 高可用性 | 大部分应用 |
- 表和字段的命名规则
可读性原则: 使用大写和小写来格式化的库对象名字,获得良好的可读性。
表意性原则: 对象的名字应该能够描述它所标识的对象
长名性原则: 尽可能少使用或者不适用缩写
- 字段类型的选择原则
3.1 列的数据类型一方面影响数据存储空间的开销,另一方面也会影响数据查询的性能。
当一个列可以选择多种数据类型的时候,应该优先考虑数字类型,其次是日期或二进制类型,最后是字符类型。
对于相同级别的数据类型,应该优先选择占用空间小的数据类型。
以上选择 主要从下面两个角度考虑
a. 在对数据进行比较(查询条件、join 条件及排序)操作时 :同样的数据,字符处理往往比数字处理慢
b. 在数据库中,数据处理以页为单位,列的长度越小,利于提升性能。
3.2 char 和 varchar 如何选择
a: 如果列中要存储的数据长度差不多是一致的,则应该考虑用char ;否则应该考虑用varchar 。
b: 如果列中最大数据长度小于50字节,则一般也考虑用char
c: 一般不宜定义大于50个字节的char类型列
3.3 decimal 与 float 如何选择
a: decimal用于存储精确数据 而float用于存储非精确数据。故精确数据类型只能选择用 decimal 类型
b: 由于float的存储空间开销比decimal小(精确到7位小数只需要4个字节 而精确到15位小数只需要8个字节)故非精确数据优先选择float类型
- 其他问题
4.1 如何选择主键 a: 区分业务主键和数据库主键 业务主键用于标识业务数据 ,进行表与表之间的关联 ,数据库主键为了优化数据库存储 (innodb会生成6个字节的 隐含主键) b: 根据数据库类型,考虑主键是否要顺序增长 有些数据库是按主键的顺序逻辑存储的 c: 主键字段所占空间尽可能的小 对于使用聚族索引方式存储的表 每个索引后都附加主键的信息
4.2 避免使用外键约束
降低数据导入的效率 增加维护的成本 虽然不建议使用外键约束,但是相关联的列上面一定要建立索引 4.3 避免使用触发器
降低数据导入的效率 可能会出现 意想不到的异常 使业务逻辑变得复杂
4.4 关于预留字段
无法准确的知道预留字段的类型 无法准确的指导预留字段的内容 后期维护预留字段的成本同增加一个字段的成本是相同的 严禁使用预留字段
5. 反范式化设计 重点
什么是反范式化?
反范式化是针对 范式化而言,所谓反范式化就是为了性能和读取效率考虑而适当对第三范式的要求进行违反,而允许存在少量的数据冗余, 换句话说反范式化就是用空间换取时间。
反范式化设计的优点:减少表的关联数量、增加数据的读取效率。
反范式化一定要适度。
结语
数据库设计的优化,我决定另开一篇讲述。