范式设计可以消除数据库的数据冗余及插入异常,但是过分的范式设计可能导致数据查询时需要关联多张表,导致数据库查询效率下降,因此在实际工作中,需要适当的反范式设计。
举例说明,某在线图书销售网站,希望实现如下功能: 1)用户登录 2)用户管理 3)商品展示 4)商品管理 5)供应商管理 6)在线销售
符合三范式的数据库设计
用户信息表 : 用户名(主键),密码,姓名,手机号,注册日期
图书信息表 : 图书名称(主键),出版社名词,图书价格图书描述,作者
分类信息表 : 分类名词(主键),分类描述
图书分类表 : (图书名词,图书分类)(主键)
供应商信息表:出版社名词(主键),地址,电话,联系人,银行帐号
订单表:订单编号(主键),用户名,下单日期,物流单号
订单图书关联表 : (订单编号,图书名称)(主键), 商品数量
在如上的数据库设计中,如果需要查询每个用户的消费总金额
select 用户名, sum(c.图书价格*b.商品数量)
from 订单表 a join 订单图书关联表 b on a.订单编号=b.订单编号
join 图书信息表 c on b.图书名称=c.图书名称
group by 用户名
以上查询需要关联3张表,因为在线销售经常会有促销活动,商品价格时而会波动,在以上设计中,如果图书价格发生变化,则查询结果也会发生变化。
如果需要查询下单用户和订单详情
select a.订单编号 a.用户名 c.图书名称 b.商品数量 c.图书价格
from 订单表 a join 订单图书关联表 b on a.订单编号=b.订单编号
join 图书信息表 c on b.图书名称=c.图书名称
以上查询也需要关联3张表格。
反范式设计 ,在 订单表 和 订单图书关联表 中增加冗余数据
订单表:订单编号(主键),用户名,下单日期,物流单号,订单金额
订单图书关联表 : (订单编号,图书名称)(主键), 商品数量,图书价格
在如上的数据库设计中,如果需要查询每个用户的消费总金额
select 用户名,sum(订单金额) from 订单表 group by (用户名)
需要查询下单用户和订单详情
select a.订单编号 a.用户名 b.图书名称 b.商品数量 b.图书价格
from 订单表 a join 订单图书关联表 b on a.订单编号=b.订单编号
反范式设计后,因为 订单图书关联表 已经保存了当时的商品价格,所以商品价格波动并不影响查询结果,而且减小查询需要关联的表。
反范式设计需要更具具体业务实际决定,将经常使用的业务表进行合理的反范式设计可以提高数据库的查询效率。
在实际的业务工作中,一般不使用外键,因为外键会在每次数据插入时进行合法性校验,这样回极大的拖累数据库的插入效率。
新闻热点
疑难解答