关于数据库反范式设计

之前并没有对这个问题有一个确切的概念,之所以要反范式,一定要知道为什么要反范式设计,设立就先从三范式说起。

从我的记忆中,三范式这么要求:

第一范式:一张表不能够有相同的字段,这是所有范式的基础。

第二范式:一张表必须要有唯一标示

第三范式:不依赖其他非主属性


上面的范式从数据库的设计角度并没有什么问题,但是,在实际的项目设计中会出现很大的问题。


举例: 使用ORM框架,如hibernate,mybatis等,如果完全的遵守范式设计,那么在效率上会存在很大的问题,

原因如下:

如hibernate查询会查询所有的记录信息,这是如果有外检一对多,多对多等关系势必影响系统效率。

另一方面,如果完全遵守范式要求,虽然在一定程度上降低了数据库的yongyu度。但是系统的可维护性会大大的下降。


如果仅仅是这量反面就有足够的理由去做反范式要求了,与其遵守范式要求,不如将更多的业务封装在代码层,这样做的好处就不言而喻了。


综上,总结处一个反范式设计的目的:用空间去换时间。

空间在这里的成本其实是远远低于时间成本的,随着项目的发布,空间成本会越来越低。


所以,反范式设计其实是一个不错的选择,特别是数据量特别和业务复杂度不高的情况下。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据库设计范式 1.范式 1.1 1NF-3NF 定义 1NF确保原⼦性(Atomicity)原⼦性的粒度、原⼦性的价值(1范式:单值,并且把值当做单值⽤,建议不要把值 拆开) 2NF检查对键的完全依赖价值在在于控制数据冗余和查询性能 3NF检查属性的独⽴性 规范化的价值合理规范化的模型可应对需求变 更 规范化数据重复降⾄最少 为什么要有三范式? 不会发⽣插⼊(insert)、删除(delete)和更新(update)操作异常。 控制数据冗余和提⾼查询性能 更好的进⾏数据有效性 检查,提⾼存储效率。 范式的满⾜便于数据⼀致性的控制 如何控制冗余? 使⽤三范式 缺点 范式化的,在查询的时候经常需要很多的关联,因为单独⼀个内不存在冗余和重复数据。这导致多次的关联,增加查询代价 可能 使⼀些索引策略⽆效。因为范式化将列存放在不同的中,⽽这些列在⼀个中本可以属于同⼀个索引。 1.2 范式(逆范式)打破范式 定义,为什么要有范式? 等级越⾼的范式设计出来的越多,可能会增加查询所需时间。当我们的业务所涉及 的⾮常多,经常会有多连接,并且我们对的操作要时间上要尽量的快,这时可以考虑我们使⽤"范式"。 范式⽤空间来换取时 间,引⼊受控的数据冗余,当查询时可以减少或者是避免之间的关联 优点 可以避免关联,因为所有的数据⼏乎都可以在⼀张上显⽰; 可以设计有效的索引; 缺点 提⾼了对数据冗余的维护,为了保证数据的⼀ 致性(可以⽤触发器来解决这个问题,某个被修改后触发另⼀个的更新) 范式的7种模式,并举例。 ⼀对⼀:合并 如果双⽅都是完全参与,那么某个直接可以作为另⼀张的属性直接合并。若有⼀⽅是 部分参与,把完全参与的并⼊部分参与的会出现空值,将部分参与并⼊完全参与的可以。若双⽅都是部分参与,⼀定会出现空值,这样就很 难确定主键 例⼦:员⼯(员⼯编号,姓名,住址,薪⽔,科室编号) 亲属(员⼯编号,亲属姓名,亲属电话),其中亲属中只登记⼀位亲 属,如果要查询张三的亲属的电话,就要连接两张,所以将两张合并以减少连接。 ⼀对多:复制⾮关键字以减少连接 适⽤条件:当两张连接时,最主要的事务都与某个⾮键值相关 例⼦:两个(⽤户id,好友id)和(⽤户 id,⽤户昵称,⽤户邮箱,联系电话)符合3NF,如果需查询某个⽤户的好友(昵称)名单,此时需对2个进⾏连接查询,可以把第⼀个修改成(⽤户 id,好友id,好友昵称)这样只需要查询第⼀个就可获取所有好友昵称. ⼀对多:复制关键字以减少连接 复制⼀对多关系中的外键,使需要通过第三张连接的两张直接关连在⼀起 在⼀对多的关系中,将另 ⼀实体的主键复制到多的实体当外键,减少join的数量 例⼦:每个部门租了⼀些录像带,每盘录像带是有租赁协议的。这样有三张:部门(部门编号),租的录像(录像带编号,部门编号),租赁 协议,见下图关系 \ 多对多:关系⾥⾯复制值以减少连接 引⼊⼀张新,多对多被拆成两个⼀对多(满⾜3NF)。 假设要查询,演员演了哪些电影,为了避免 三张连接,就在role中复制电影名称以减少连接 \ 引⼊重复组 引⼊重复组,重复组⼀般不超过10个 (对于⼀个多值属性,如果多值的数量不多⼩于等于10) 例⼦:customer 可能有多个 address。⼀般是customer⼀张,address⼀张,address中存储它对应的customer的ID那么每次付款的时候,需要再查找address 来得到customer的所有地址。可以在customer后⾯加addr1、addr2字段,但不知道要加多少个,不好。较为常见的做法是,在 customer中引⼊⼀条addr字段,放最常⽤地址,address中存储所有地址。 提取 extract table的中内容和原可能都相同,只是组织结构不同,有可能⼀个是为了查询⽽建的(将经常被查询的数据提前计算 出来存⼊该,会有⼤量冗余,但是提⾼效率),另⼀个是为了update的,⼀定程度上实现了读写分离。 ⽐如有学⽣,宿舍,为了查学 ⽣的住宿费,需要连接两。此时可以提取出⼀张⽤于查询的,其中包含了学⽣姓名,住宿费⽤以及其他字段,⽅便查询。 使⽤分区 可以将分解成更少的分区。 ⽔平分区:跨多个(较⼩)的分配记录。这种形式分区是对的⾏进⾏分区,通过这样的⽅式 不同分组⾥⾯的物理列分割的数据集得以组合,从⽽进⾏个体分割(单分区)或集体分割(1个或多个分区)。所有在中定义的列在每个数据集 中都能找到,所以的特性依然得以保持。 例⼦:⼀个包含⼗年发票记录的可以被分区为⼗个不同的分区,每个分区包含的是其中⼀年 的记录。 垂直分区:跨多个(较⼩)分布列。 PK复制,以便重建。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值