Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

数据库——SQL

  • 服务器可以轻松扩展n台,但用的还是一个数据库,性能会有瓶颈

    • 数据库需要横向扩展,但是多个拷贝情况下要考虑一致性的问题
      • 所以要学习 replication(复制)
    • 数据库需要做拆分,但是各个部分可能互相依赖
      • 所以要学习 partitioning(分区)
    • 数据库需要移除复杂语句,避免复杂查询
      • 所以要学习 denormalizaion(反范式化)
  • 数据库复制 Database replication

    • 从单库扩展到多库,同时部署多个,分为主库和从库,一个主库只承担写操作,并把更新复制到从库,多个从库负责承担读取的压力,做到读写分离
    • 这种保证一致性的复制机制,就叫replication
    • 这种复制分为3种:
      • 同步复制
        • 需要等从库确认,会产生延时,且可能因网络问题失败
      • 异步复制
        • 不需要等从库确认,会破坏数据一致性
      • 半同步复制
        • 一部分实例是同步的(高一致性)
        • 另一部分是异步的(高响应性)
    • 参考文章 Database Replication_系统设计笔记9 | 黯羽轻扬
  • 数据库分区 Database partitioning

    • 单库单机器的硬件资源和处理能力有限,需要把单库拆分为多库(而不仅仅是完全复制多份)

    • 把逻辑数据库(比如表),拆分成各个部分独立部署更小的库,就叫partitioning

    • 这种拆分分为3种:

      • 水平分区(也叫sharding分片):
        • 按行拆分,把不同行拆分到不同的表中,schema表结构不变
        • 关键是选取分片字段,尽量保证均衡
          • 这里的均衡指的是最终访问流量均衡,而不仅是数据量相等
      • 垂直分区:
        • 按列拆分,把一些列放到其他表中
      • 功能分区: 按业务拆分,把不同业务的独立数据分开
    • 代价

      • 跨分区join查询慢
        • 办法:把join交给应用层
      • 全表查询慢
        • 办法:尽量准确定位分区
      • 不支持事务操作
        • 办法:把事务交由应用层
      • 负载容易不均衡导致效果差
        • 办法: 应该监控并定期调整
  • 数据库反范式化 Database denormalizaion

    • 范式化是什么
      • 简单版: 按照一系列范式(Normal forms),组织数据模型,减少数据冗余,提高数据完整性
      • 三大范式
        • 1NF: 要求数据表中每个字段的值都不可再分
        • 2NF: 在1NF基础上,要求所有非主属性都完全依赖于其主键
        • 3NF: 在2NF基础上,要求所有非主属性的不传递依赖与任何主键
      • 作用
        • 相当于数据层的设计模式,对数据表进行解耦,是单表信息更加内聚,彼此边界分明
    • 范式化的弊端
      • 在这种约束下,相关联的信息 被存储到 不同的逻辑表 中
      • 导致经常需要多表join联查,关系越复杂,查询越慢
        • 改善方法
          • 引入冗余,比如
            • 允许DBMS存储额外的信息,例如索引视图,物化视图等,但仍遵守范式
            • 直接打破设计范式
    • 反范式
      • 是一种针对 遵从设计范式的数据库的 性能优化策略
        • 注意: 反范式化不等于非范式化,一定是在范式设计上才能做调整,从而打破规则
      • 实现方式
        • 把某些数据在不同的地方多放几份,避免跨表联查,相当于牺牲一部分写入性能,换取更高的读取性能
          • 比如在一对多关系中,把“多”的数量作为“一”的属性存储起来
        • 预先连接(pre-joined)生成汇总表:把需要频繁join的表提前join好
        • 采用硬编码值:把依赖表中的常量值(或者不经常变化的值)直接硬编码到当前表中,从而避免join操作
        • 把详情信息纳入主表中:对于数据量不大的详情表,可以把全部/部分详情信息塞到主表中,以避免join操作
      • 代价
        • 除非必要,一般不建议反范式化,因为代价高昂
        • 会失去数据完整性保障,一致性需要DBA自己保证
        • 牺牲了写入速度,更新时要修改多处(但大多数场景都是读密集)
        • 消耗更多存储空间(但空间换时间,还能接受)
    • 比起 范式 后采取 反范式,还不如一开始就用反范式设计——直接用NoSQL