数据库——SQL
-
服务器可以轻松扩展n台,但用的还是一个数据库,性能会有瓶颈
- 数据库需要横向扩展,但是多个拷贝情况下要考虑一致性的问题
- 所以要学习 replication(复制)
- 数据库需要做拆分,但是各个部分可能互相依赖
- 所以要学习 partitioning(分区)
- 数据库需要移除复杂语句,避免复杂查询
- 所以要学习 denormalizaion(反范式化)
- 数据库需要横向扩展,但是多个拷贝情况下要考虑一致性的问题
-
数据库复制 Database replication
- 从单库扩展到多库,同时部署多个,分为主库和从库,一个主库只承担写操作,并把更新复制到从库,多个从库负责承担读取的压力,做到读写分离
- 这种保证一致性的复制机制,就叫replication
- 这种复制分为3种:
- 同步复制
- 需要等从库确认,会产生延时,且可能因网络问题失败
- 异步复制
- 不需要等从库确认,会破坏数据一致性
- 半同步复制
- 一部分实例是同步的(高一致性)
- 另一部分是异步的(高响应性)
- 同步复制
- 参考文章 Database Replication_系统设计笔记9 | 黯羽轻扬
-
数据库分区 Database partitioning
-
单库单机器的硬件资源和处理能力有限,需要把单库拆分为多库(而不仅仅是完全复制多份)
-
把逻辑数据库(比如表),拆分成各个部分独立部署更小的库,就叫partitioning
-
这种拆分分为3种:
- 水平分区(也叫sharding分片):
- 按行拆分,把不同行拆分到不同的表中,schema表结构不变
- 关键是选取分片字段,尽量保证均衡
- 这里的均衡指的是最终访问流量均衡,而不仅是数据量相等
- 垂直分区:
- 按列拆分,把一些列放到其他表中
- 功能分区: 按业务拆分,把不同业务的独立数据分开
- 水平分区(也叫sharding分片):
-
代价
- 跨分区join查询慢
- 办法:把join交给应用层
- 全表查询慢
- 办法:尽量准确定位分区
- 不支持事务操作
- 办法:把事务交由应用层
- 负载容易不均衡导致效果差
- 办法: 应该监控并定期调整
- 跨分区join查询慢
-
-
数据库反范式化 Database denormalizaion
- 范式化是什么
- 简单版: 按照一系列范式(Normal forms),组织数据模型,减少数据冗余,提高数据完整性
- 三大范式
- 1NF: 要求数据表中每个字段的值都不可再分
- 2NF: 在1NF基础上,要求所有非主属性都完全依赖于其主键
- 3NF: 在2NF基础上,要求所有非主属性的不传递依赖与任何主键
- 作用
- 相当于数据层的设计模式,对数据表进行解耦,是单表信息更加内聚,彼此边界分明
- 范式化的弊端
- 在这种约束下,相关联的信息 被存储到 不同的逻辑表 中
- 导致经常需要多表join联查,关系越复杂,查询越慢
- 改善方法
- 引入冗余,比如
- 允许DBMS存储额外的信息,例如索引视图,物化视图等,但仍遵守范式
- 直接打破设计范式
- 引入冗余,比如
- 改善方法
- 反范式
- 是一种针对 遵从设计范式的数据库的 性能优化策略
- 注意: 反范式化不等于非范式化,一定是在范式设计上才能做调整,从而打破规则
- 实现方式
- 把某些数据在不同的地方多放几份,避免跨表联查,相当于牺牲一部分写入性能,换取更高的读取性能
- 比如在一对多关系中,把“多”的数量作为“一”的属性存储起来
- 预先连接(pre-joined)生成汇总表:把需要频繁join的表提前join好
- 采用硬编码值:把依赖表中的常量值(或者不经常变化的值)直接硬编码到当前表中,从而避免join操作
- 把详情信息纳入主表中:对于数据量不大的详情表,可以把全部/部分详情信息塞到主表中,以避免join操作
- 把某些数据在不同的地方多放几份,避免跨表联查,相当于牺牲一部分写入性能,换取更高的读取性能
- 代价
- 除非必要,一般不建议反范式化,因为代价高昂
- 会失去数据完整性保障,一致性需要DBA自己保证
- 牺牲了写入速度,更新时要修改多处(但大多数场景都是读密集)
- 消耗更多存储空间(但空间换时间,还能接受)
- 是一种针对 遵从设计范式的数据库的 性能优化策略
- 比起 范式 后采取 反范式,还不如一开始就用反范式设计——直接用NoSQL
- 范式化是什么