之前的两篇笔记中谈到了从单库扩展到多库以承载更多的请求量以及单库(表)拆分成多库(表),打破单库的性能瓶颈。
这都是为了应对大数据量下的措施。
然而,除却数据量外,还有一个极其影响单库性能的因素——数据的组织方式。
对于关系型数据库,我们可以尝试在一定程度上改变数据的组织方式,即反范式化(Denormalization)

关于范式

可以参考以前做的笔记:
《MySQL——数据表设计三大范式》
设计范式相当于数据层的设计模式,对数据表进行解耦,使单表信息更加内聚,彼此边界分明,依赖关系更加清晰.
试想,如果相同的信息在多行中重复出现,不相干的信息也凑在同一张表中,就很容易出现一些异常情况:

  • 更新异常:只更新单行,就会出现逻辑上的不一致
  • 插入异常:无法只插入部分信息,除非让其它列先留空
  • 删除异常:删除部分信息的同时,可能会波及其它无关信息

范式化的弊端

在这些设计范式的约束下,相关联的信息被存储到了不同的逻辑表中,以致于经常需要多表联查(join操作),关系越复杂,连表查询越慢。例如分成客户表和订单表和商户表,当我们要执行的操作与这张表的部分信息都有关时,就需要进行多表join。
那么,有办法能改善查询性能吗?

  • 允许 DBMS 存储额外的冗余信息,例如索引视图(indexed views)、物化视图(materialized views),但仍遵从设计范式
  • 增加冗余数据,减少join操作,打破设计范式(即反范式化)

反范式化

所谓反范式化,是一种针对遵从设计范式的数据库(关系模式)的性能优化策略。
反范式化不等于非范式化(Unnormalized form),反范式化一定发生在满足范式设计的基础之上。前者相当于先遵守所有规则,再进行局部调整,故意打破一些规则,而后者全然不顾规则。
反范式化通过增加冗余数据或对数据进行分组,牺牲一部分写入性能,换取更高的读取性能:
在设计范式的约束下,数据表中没有冗余信息(某个数据只存放在某张表的某个单元格中),为了得到某个数据可能需要一系列的跨表查询,因而读操作性能不佳,但写操作很快,因为更新数据时只需要修改一处。
反范式化就是要打破这种约束,把某些数据在不同的地方多放几份,以加快数据检索速度。
具体操作如下:

  • 存一些派生数据:类似于往 Redux Store 中塞计算属性,把需要频繁重复计算的结果存起来,例如在一对多关系中,把“多”的数量作为“一”的属性存储起来
  • 预先连接(pre-joined)生成汇总表:把需要频繁join的表提前join好
  • 采用硬编码值:把依赖表中的常量值(或者不经常变化的值)直接硬编码到当前表中,从而避免join操作
  • 把详情信息纳入主表中:对于数据量不大的详情表,可以把全部/部分详情信息塞到主表中,以避免join操作

反范式化的代价

  • 失去了数据完整性保障:打破范式,意味着之前通过范式化解决的更新、插入、删除异常问题又将重新冒出来,也就是说,冗余数据的一致性要靠 DBA 自己来保证,而不像索引视图等由 DBMS 来保证
  • 牺牲了写入速度:由于反范式化引入了冗余数据,更新时要修改多处,但大多数场景都是读密集的,写入慢一点问题不大
  • 浪费了存储空间:存储了不必要的冗余数据,自然会浪费一些存储空间,但空间换时间一般是可接受的(毕竟内存、硬盘等资源已经相对廉价了)

参考

http://www.ayqy.net/blog/database-denormalization/

后台系统可扩展性学习笔记(十一)Database Denormalization相关推荐

  1. 后台系统可扩展性学习笔记

    整理了一下笔记目录,将以前学习的一些知识串联起来了,比如cdn.负载均衡.中间件,以前只是各自了解了一点,现在大概理清了后台系统设计中他们各自的作用. 后台系统可扩展性学习笔记(一)概要 后台系统可扩 ...

  2. 后台系统可扩展性学习笔记(十)Database Partitioning

    为了提升数据库的处理能力,我们把单库扩展成多库,并通过更新同步机制(即Replication)来保证多份数据的一致性.然而,在 各种复制方案下,每个数据库都持有一份完整数据,基于全量数据提供增删改查服 ...

  3. 后台系统可扩展性学习笔记(十四)异步机制与MQ

    对于 Web 服务而言,提升可扩展性的主要途径是将耗时的同步工作改成异步处理,从而允许将这些工作"外包"给多个 Worker 去做,或者提前完成能够预知的部分. 异步机制与可扩展性 ...

  4. 后台系统可扩展性学习笔记(一)概要

    文章目录 系统大致架构 可扩展性 负载均衡器与会话保持 引入冗余增强系统可用性 缓存减轻数据库压力 异步处理 参考 系统大致架构 当一个用户请求从客户端出发,经过网络传输,达到 Web 服务层,接着进 ...

  5. 后台系统可扩展性学习笔记(十二)NoSQL

    文章目录 NoSQL定义 NoSQL种类 键值存储 文档存储 宽列存储 图形数据库 NoSQL 意味着什么 ACID vs. BASE SQL or NoSQL NoSQL定义 不同于关系型数据库,N ...

  6. 后台系统可扩展性学习笔记(十三)缓存

    文章目录 在哪儿加缓存 缓存什么内容 缓存原始查库结果 缓存数据对象 怎么查询缓存结果 预留缓存模式 直读模式 直写模式 回写式缓存 绕写式缓存 提前刷新模式 缓存满了如何处理 参考 读写分离.分库分 ...

  7. 后台系统可扩展性学习笔记(七)Service Discovery与微服务

    文章目录 应用层 微服务架构 服务注册查询 Service Discovery 客户端 Service Discovery DNS-SD DNS-based Service Discovery 服务端 ...

  8. 后台系统可扩展性学习笔记(五)负载均衡

    文章目录 Load balancer(负载均衡器) 请求传输拆解 DNS 负载均衡 客户端负载均衡 OSI 七层模型回顾 2 层.3 层负载均衡 3/4 层负载均衡 7 层负载均衡 在 第一节谈到了系 ...

  9. 后台系统可扩展性学习笔记(三)DNS机制原理

    文章目录 DNS概念梳理 域名基本概念 资源记录基本概念 路由策略 DNS 域空间结构 实现原理 复制机制 查询机制 缓存机制 参考 DNS概念梳理 DNS(Domain Name System)相当 ...

最新文章

  1. android简化log输出方法
  2. 解决java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed
  3. 我们无法在你选择的位置安装Windows。0x80300002
  4. PHP的统一换行PHP_EOL
  5. uni-app官方教程学习手记
  6. tidb vs mysql_一个长耗时SQL在TiDB和Mysql上的耗时测试
  7. mysql ascii ord_MySQL ORD()函数使用实例介绍
  8. 姓名的首字母组成的图案C语言怎么编,c语言编写一个程序,根据用户输入英文名和姓先显示姓氏,其后跟一个逗号,然后显示名的首字母:...
  9. ros 开源物体检测_ROS kinetic + Realsens D435i + ORK + LINEMOD 物体识别
  10. Linux操作系统基础原理
  11. SCI 论文免费下载地址
  12. linux 中文 文件名乱码,中文文件名乱码问题
  13. Ureport2报表工具金额格式化
  14. Linux下使用为知笔记的坑和解决办法
  15. 09-03 NOIP模拟测试36
  16. js定时换图片(图片路径可变)
  17. 视频原声能去掉吗?怎么批量处理
  18. VB.NET MsgBox详解 vs2010
  19. 计算机技术水平考核试卷带答案,中小学教师计算机技术水平考核试卷笔试题带答案...
  20. 怎样修改计算机用户文件名,win10修改用用户文件夹名字怎么操作_win10更改用户文件夹名称方法...

热门文章

  1. 2021年程序员可以做哪些副业?
  2. html5测试题整理--针对标签的概念性
  3. 计算机考研数学基础知识点,2019计算机考研数学复习:打好基础是必须的啊喂!...
  4. 请领导批阅文件怎么说_刚到公司,应该怎么喊领导,别直接说名字,高情商这样称呼...
  5. mysql 快照能否恢复某个表_mysql全库备份恢复某个表
  6. linux共享磁盘给指定ip,linux想挂载通过ipsan协议推送上来的磁盘,两个ip共分配了21个未分区的盘,...
  7. java开机自启动 Linux,java项目jar包开机自启(WINDOWS,Linux)
  8. uniapp uni.request GET方式请求,不能直接传数组解决方法
  9. jquery 给iframe里的元素添加事件
  10. css3 flex 布局