优良的设计 | 槽糕的设计 |
---|---|
减少数据冗余 | 存在大量的数据冗余 |
避免数据维护异常 | 存在数据插入、更新、删除异常 |
节约存储空间(偶尔会用空间换时间) | 浪费大量存储空间 |
高效的访问 | 访问数据低效 |
设计的基本步骤
1). 需求分析
需求分析主要完成的内容:业务系统中有哪些数据?这些数据又有哪些属性?数据和属性的各自特点有哪些?
2). 逻辑设计
使用ER图设计工具对数据库进行ER图逻辑建模:首先将需求转化为数据库的逻辑模型,其次,通过ER图形式将逻辑模型描述展示出来,最后这个逻辑设计与所选择的DBMS无关,也就是说这个逻辑设计应该适合所有的DBMS。
3). 物理设计
这个阶段是进入到与DBMS相关的阶段,因此首先需要选择DBMS,并且将第二步的逻辑模型转为物理模型。
这个阶段会涉及到数据库中建表,选择字段类型的问题。在MySql中遵循以下原则:
列的数据类型一方面影响相应数据的存储空间的开销,另一方面也会影响数据查询性能。当一个列可以选择多种数据类型时,应该优先考虑数字类型,其次是日期或二进制,最后是字符串类型。对于相同级别的数据类型,在满足业务的情况下,应该优先选择占用空间小的数据类型。
mysql中部分字段空间占用情况:
额外注意几点:
4). 维护优化
订单编号 | 商品编号 | 商品名称 | 数量 | 单位 | 价格 | 客户 | 联系方式 |
---|---|---|---|---|---|---|---|
001 | 1 | 挖掘机 | 1 | 台 | 12000.00 | 张三 | 028-88886666 |
001 | 2 | 冲击钻 | 8 | 把 | 260.00 | 张三 | 028-88886666 |
002 | 3 | 铲车 | 3 | 辆 | 32000.00 | 李四 | 028-88886666 |
问题:这个表中是以订单编号和商品编号作为联合主键。这样在该表中商品名称、单位、商品价格等信息不与该表的主键相关,而仅仅是与商品编号相关。所以在这里违反了第二范式的设计原则。
解决办法:将以上的表进行拆分,订单信息保存一张表,订单中所拥有的商品以后咱表,最后商品信息一张表
订单信息
订单编号 | 客户 | 联系方式 |
---|---|---|
001 | 张三 | 028-88886666 |
001 | 张三 | 028-88886666 |
002 | 李四 | 028-88886666 |
订单商品
订单编号 | 商品编号 | 数量 |
---|---|---|
001 | 1 | 1 |
001 | 2 | 8 |
002 | 3 | 3 |
商品信息
商品编号 | 商品名称 | 单位 | 商品价格 |
---|---|---|---|
1 | 挖掘机 | 台 | 12000.00 |
2 | 冲击钻 | 个 | 260.00 |
3 | 铲车 | 辆 | 32000.00 |
3. 第三范式(3NF)
概念:基于2NF基础上的,如果数据表中不存在非关键字段对任意候选关键字段的传递函数依赖则符合第三范式。
作用:确保每列都和主键列直接相关,而不是间接相关
举例:在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。这样会减少数据冗余(但在实际开发中,为便于查询,往往会在订单表中增加一些客户信息的冗余)
4. BC范式(BCNF)
概念:在第三范式的基础之上,数据库表中如果不存在任何字段对任一候选关键字段的传递函数依赖则符合BC范式。也就是说如果是复合关键字,则复合关键字之间也不能存在函数依赖关系。
作用:确保任意列都和主键列直接相关,而不是间接相关
举例:在设计一个供应商与供应商联系人表时,供应商联系人只能在一家供应商中上班,供应商可以供应多个商品。因此选用:供应商+联系人来作为联合主键,然而这二者之间存在传递依赖关系
问题表:
供应商 | 商品ID | 供应商联系人 | 商品数量 |
---|---|---|---|
饮料一厂 | 1 | 张三 | 10 |
饮料一厂 | 2 | 李四 | 20 |
饮料一厂 | 1 | 王五 | 10 |
这个表存在以下符合主键的依赖关系:供应商->供应商联系人 供应商联系人->供应商
解决办法:
供应商
供应商 | 商品ID | 商品数量 |
---|---|---|
饮料一厂 | 1 | 10 |
饮料一厂 | 2 | 20 |
饮料一厂 | 1 | 10 |
供应商联系人
供应商 | 供应商联系人 |
---|---|
饮料一厂 | 张三 |
饮料一厂 | 李四 |
饮料一厂 | 王五 |
为了设计出优良的数据库,我们需要遵循数据库的范式,但是有时候如果你设计的数据库完全遵循了这些范式,反而会降低你的某些性能。这里提几点:
- 数据库连接会带来一部分性能损失,因此有时候为了减少冗余,将数据存放在多张表中,往往会降低查询性能,而互联网的世界,读写比例大概是3:1甚至4:1
- 减少表与表之间的关联数量(减少了对磁盘的IO),增加数据的读取效率。
- 反范式化一定要适度。凡事过度适得其反。
举例反范式化设计:
遵循范式设计表:
用户表(用户id, 姓名, 电话, 地址, 邮编)
订单表(订单id, 用户id, 下单时间, 支付类型, 订单状态)
订单商品表(订单id, 商品id, 商品数量, 商品价格)
商品表(商品id, 名称, 描述, 过期时间)
反范式设计表
用户表(用户id, 姓名, 电话, 地址, 邮编)
订单表(订单id, 用户id, 下单时间, 支付类型, 订单状态, 订单价格, 姓名, 地址, 电话)
订单商品表(订单id, 商品id, 商品数量, 商品价格, 商品名称,过期时间)
商品表(商品id, 名称, 描述, 过期时间)
通过以上反范式设计带来的好处:
当需要查询订单购买者相关信息时,以前需要拿到订单号,在订单表中找到用户id,然后去用户表查询用户信息,再到订单商品表中找到商品id,再去商品表中找到商品信息。这就需要查询4张表,通过反范式的设计,现在只需要在订单表可以获得订单与用户的信息,再到订单商品表中,即可获得订单与商品的信息。从4张表的查询变为2张表,用空间换时间,是值得的。
当然这里在进行更新操作的时候就需要注意了。
原文地址:http://blog.csdn.net/hel12he/article/details/44997209