数据库设计
简介
简单来说,数据库设计就是根据业务系统的具体需要,结合我们所选的数据库管理系统,为这个业务系统构造出最优的数据库存储模型.并建立好数据库中的表结构及表与表之间的关联关系的过程.使之能有效的对应应用系统中的数据进行存储,并可以高效的对已经存储的数据进行访问.
-
常用关系型数据库:mysql、Oracle、SQL server、PgSql
-
常用非关系型数据库:Mongo、Memcache、Redis
数据库设计作用
优良的设计 | 糟糕的设计 |
---|---|
减少数据冗余 | 存在大量数据冗余 |
避免数据维护异常 | 存在数据插入,更新,删除异常 |
节约存储空间 | 浪费大量存储空间 |
高效的访问 | 访问数据低效 |
维护调整方便 | 较难调整维护 |
数据库设计步骤
-
需求分析
-
数据库是什么
-
数据库有哪些属性
-
数据库和属性各自的特点有哪些
-
-
逻辑设计
- 使用ER图对数据库进行逻辑建模
-
物理设计
- 根据使用的数据库自身的特点把逻辑设计转换为物理设计
-
维护优化
-
新需求进行表建立
-
索引优化
-
大表拆分
-
需求分析
1.了解系统中所要存储的数据
2.了解数据的存储特点
3.了解数据的生命周期
需求分析要搞清以下问题
-
实体及实体之间的关系(1对1,1对多,多对多)
-
实体所包含的属性有什么
-
哪些属性或属性的组合可以唯一标识一个实体
实例演示需求分析过程
-
以小型电子商务网站为例,包含的模块:
-
用户模块
-
包括属性:用户名、密码、电话、邮箱、身份证号、地址、姓名、昵称
-
可选唯一标识属性:用户名、身份证、电话
-
存储特点:随系统上线时间逐渐增加,需要永久存储;在物理设计中对用户模块考虑分库和分表的问题
-
-
商品模块
-
包括属性:商品编码、商品名称、商品描述、商品品类、供应商名称、重量、有效期、价格…
-
可选唯一标识属性:(商品名称、供应商名称组合)、(商品编码)
-
存储特点:对于下线商品可以归档存储,不在销售的商品可以迁移到其它表中,使商品表保持小数量级
-
-
订单模块
-
包括属性:订单号、用户姓名、用户电话、收货地址、商品编号、商品名称、数量、价格、订单状态、支付状态、订单类型
-
可选唯一标识属性:订单号
-
存储特点:永久存储(分表、分库存储)
-
-
购物车模块
-
包括属性:用户名、商品编号、商品名称、商品价格、商品描述、商品分类、加入时间、商品数量
-
可选唯一标识:(用户名、商品编号、加入时间组合)、购物车编号
-
存储特点:不用永久存储(设置归档,清理归档)
-
-
供应商模块
-
包括属性:供应商编号、供应商名称、联系人、电话、营业执照、地址、法人
-
可选唯一标识:供应商编号、营业执照号
-
存储特点:永久存储
-
-
-
关系图
逻辑设计
逻辑设计要做什么
-
将需求转化为数据库的逻辑模型
-
通过ER图的形式对逻辑模型进行展示
-
同所选用的具体的DBMS系统无关
数据库设计专业词
-
关系:一个关系对应通常所说的一张表
-
元组:表中的一行即为一个元组,对应一个实体
-
属性:表中的一列即为一个属性,每一个属性都有一个名称,称为属性名
-
候选码:表中的某个属性组,它可以唯一确定一个元组,可以理解为主键或唯一索引
-
主码:一个关系有多个候选码,选定其中一个为主码,使表中的主键
-
域:属性的取值范围
-
分量:元组中的一个属性,性别的男和女
ER图例说明
-
矩形:标识实体集,矩形内写实体集的名字
-
菱形:表示联系集
-
椭圆:表示实体的属性
-
线段:将属性连接到实体集,或将实体集连接到联系集
设计范式概要
- 常见的数据库设计范式包括第一范式、第二范式、第三范式及BC范式
数据操作异常j及数据冗余
-
操作异常
-
插入异常:如果某实体随着另一个实体的存在而存在,即缺少某个实体时无法表示这个实体,那么这个表就存在插入异常
-
更新异常:如果更改表所对应的某个实体实例的单独属性时,需要将多行更新,那么就说这个表存在更新异常
-
删除异常:如果删除表的某一行来反应某实体实例失效时导致另一个不同实体实例信息丢失,那么这个表中就存在删除异常
-
-
数据冗余
- 是指相同的数据在多个地方存在,或者说表中的某个列可以由其它列计算得到,这样就说表中存在着数据冗余
第一范式
- 定义:数据库表中的所有字段都是单一属性,不可再分的,这个单一属性是由基本的数据类型所构成的,如整数、浮点数、字符串等;也就是说第一范式要求数据库中的表都是二维表
第二范式
-
定义:数据库的表中不存在非关键字段对任一候选关键字段的部分函数依赖。
-
部分函数依赖是指存在着组合关键字(是指一个属性决定不了数据的唯一性,必须多个属性组合表示)中的某一关键字决定非关键字的情况
-
所有单关键字段的表都符合第二范式
-
-
不符合第二范式的表会存在以下问题(供应商商品表)
-
插入异常
-
删除异常
-
更新异常
-
数据冗余
-
-
供应商商品表不符合第二范式,我们可以把表拆分为商品表、供应商表、关系表
第三范式
-
定义:第三范式是在第二范式基础上定义的,如果数据表中不存在非关键字段对任意候选关键字段的传递函数依赖,则符合第三范式
-
商品分类表中,商品名称可决定分类,分类决定分类描述,所以非关键字段分类描述对关键字段商品名称有传递依赖关系
-
很多商品有相同的分类和分类描述,数据大量重复代表数据冗余
-
同时存在插入、更新、删除异常
-
BC范式
-
定义:在第三范式基础之上,数据库表中如果不存在任何字段对任一候选关键字段的传递函数依赖则符合BC范式;也就是说如果是符合关键字,则符合关键字之间也不能存在函数依赖关系
-
供应商商品表
-
复合关键字a(供应商,商品id)->复合关键字b(联系人,商品数量)
-
复合关键字c(联系人,商品id)->复合关键字d(供应商,商品数量)
-
在这里供应商可以决定供应商联系人,供应商联系人可以影响供应商,所以不符合BC范式
-
物理设计
物理设计要做什么
1.选择合适的数据库管理系统:
-
Oracle、SqlServer、Mysql、PgSql
-
商业数据库Oracle和SqlServer,非商业数据库Mysql和PgSql
-
Oracle:性能好,适合大的事务操作
-
SqlServer:微软支持,只能在window下运行
-
mysql的存储引擎有:MyISAM、MRG_MYISAM、Innodb、Archive、Ndb cluster
-
商业数据库多用于企业级项目,开源数据库多用于互联网项目
-
2.定义数据库、表及字段的命名规范
-
所有数据库命名应该遵循以下规则
-
可读性原则:使用大写和小写来格式化的库对象名字以获得良好的可读性(有些数据库系统对大小写敏感)
-
表意性原则:对象的名字应能描述它表述的对象
-
长名原则:尽可能少使用或者不使用缩写
-
数据库字段类型选择
-
字段类型的选择原则:列的数据类型一方面影响数据存储空间的开销,另一方面也会影响数据查询性能。当一个列可以选择多种数据类型时,应该优先考虑数字类型,其次是日期或二进制类型,最后是字符类型。对于相同级别的数据类型,应该优先选择占用空间小的数据类型。
-
mysql中字段占用字节
列类型 存储空间 TINYINT 1字节 SMALLINT 2个字节 MEDIUMINT 3个字节 INT 4个字节 BINGINT 8个字节 DATE 3个字节 DATETIME 8个字节 TIMESTAMP 4个字节 CHAR(M) M字节,1<=M<=255 VARCHAR(M) L+1字节,L<=M -
mysql字段类型选择考虑角度
-
在对数据库进行比较(查询条件、JOIN条件及排序)操作时:同样的数据,字符处理往往比数字处理慢
-
在数据库中,数据处理以页为单位,列的长度越小,利于性能提升
-
char与varchar如何选择
-
如果列中要存储的数据长度差不多是一致的,则应该考虑用char;否则应该用varchar
-
如果列中的最大数据长度小于50Byte,则一般也考虑用char(当然,如果这个列很少用,则基于节省空间和I/O的考虑,还是可以选择varchar)
-
一般不宜定义大于50byte的char类型
-
-
decimal和float的选择
-
decimal用于存储精确数据,而float只能用于存储非精确数据,故精确数据只能选择用decimal类型
-
由于float存储空间开销较小(精确到7位小数只需要4个字节,而精确到15位小数只需8个字节),故非精确数据优先选择float类型
-
-
时间类型
-
使用int存储时间戳
-
优点:字段长度比datetime小
-
缺点:使用不方便,要进行函数转换
-
限制:只能存储到2038-1-19 11:14:07即2^32为2147483648
-
-
需要存储的时间粒度
-
-
数据库设计
-
数据库设计其它注意事项
-
区分业务主键和数据库主键:业务主键用于标识业务数据,进行表与表之间的关联;数据库主键为了优化数据存储(没设置主键Innodb会生成6个字节的隐含主键)
-
根据数据库的类型,考虑主键是否要顺序增长,有些数据库是按主键的顺序逻辑存储的
-
主键的字段类型所占用的空间要尽可能小:对于使用聚集方式存储的表,每个索引后都会附加主键信息
-
避免使用外键约束,在高并发互联网项目中外键会有负面影响
-
降低数据导入的效率
-
增加维护成本
-
虽然不建议使用外键约束,但是相关联的列上一定要建立索引
-
-
避免使用触发器
-
降低数据导入效率
-
可能会出现意想不到的数据异常
-
使业务逻辑变的复杂
-
-
关于预留字段
-
无法准确知道预留字段的类型
-
无法准确的知道预留字段中存储的数据内容
-
后期维护预留字段所要的成本,同增加一个字段所需要的成本是相同的
-
严禁使用预留字段
-
-
反范式化表设计
-
反范式化就是为了性能和读取效率的考虑而适当的对第三范式的违反,而允许存在少量的数据冗余,换句话反范式化就是用空间换取时间
-
例如在查询商品订单时关联信息涉及多张表,可以在订单表中添加订单价格、姓名、地址、电话;在订单商品表中添加商品名称、过期时间
-
反范式化设计
-
减少表的关联数量
-
增加数据的读取效率
-
反范式化一定要适度
-
-
-
维护优化
维护和优化要做什么
-
维护数据字典
-
维护索引
-
维护表结构
-
在适当的时候对表进行水平拆分或垂直拆分
维护数据字典
-
使用第三方工具对数据字典进行维护
-
利用数据库本身的备注字段来维护数据字典,对字段备注;导出数据字典
维护索引
-
如何选择合适的列建立索引
-
出现在where从句,group by从句,order by从句
-
可选择性高的列要放到索引的前面
-
索引中不要包括太长的数据类型
-
-
索引注意事项
-
索引并不是越多越好,过多的索引不但会降低写效率而且会降低读的效率
-
定期维护索引碎片
-
在sql语句中不要使用强制索引关键字
-
表结构维护
-
注意事项
-
使用在线变更表结构的工具:mysql5.6之后本身支持在线表结构的变更
-
同时对数据字典进行维护
-
控制表的宽度和大小
-
-
数据库中适合的操作
-
批量操作
-
禁止使用select*这样的查询
-
控制使用用户自定义函数
-
不要使用数据库中的全文索引
-
-
数据库表的拆分
-
垂直拆分:为了控制表的宽度可以进行表的垂直拆分
-
经常一起查询的列放到一起
-
text,blob等大字段拆分到附加表中
-
-
水平拆分
- 水平拆分表数据结构相同,就是把原来的一张拆分(复制)为多份
-
来源:51CTO
作者:凡曦
链接:https://blog.csdn.net/u013165496/article/details/100826140