关系型数据库集群性能优化

Feb 3, 2022 20:00 · 952 words · 2 minute read Dababase Architecture

1. 优化原则

SQL 优化 > 缓存 > 读写分离 > 分库分表

2. 读写分离

将数据库读写操作分散到不同的节点上:

  • 数据库服务器使用主从架构(1 主 n 从)
  • 主库读写,从库只读
  • 通过复制同步主从,每台数据库服务器都存储了所有的业务数据
  • 业务服务将写操作发送给主库,读操作发送给从库

引入问题:

  • 复制延迟
  • 分配机制

2.1 复制延迟

可能因为延迟从库还未同步。

解决复制延迟的几个常见方法:

  1. 写操作后的读操作指定发送给主库

    和业务强绑定

  2. 读从库失败后再读一次主库

    二次读取,增加主库压力

  3. 关键业务读写指向主库,非关键业务读写分离

    注册、登录业务读写都在主库完成,延迟影响较小的业务读写分离

2.2 分配机制

读写操作访问不同的数据库服务器。

  1. 程序代码封装

    在代码中抽象一个数据访问层,实现读写操作分离和数据库服务器连接的管理

    • 实现简单
    • 每个编程语言都要实现,无法通用
    • 故障时主从切换可能要修改配置和重启系统
  2. 中间件封装

    独立一套系统出来,实现读写操作分离和数据库服务器连接的管理 对于业务服务器来说,访问中间件和访问数据库没有区别

    • 与编程语言解耦,支持 SQL 接口即可
    • 数据库中间件要支持完整的 SQL 语法和数据库服务器的协议,实现复杂,细节多
    • 高性能高可用,所有的数据库操作请求都要经过中间件
    • 数据库主从切换业务无感知

3. 分库

按照业务模块将数据分散到不同的数据库服务器。

存在的问题:

  1. JOIN 操作
  2. 事务
  3. 服务器成本

小公司初创业务,不建议分库:

  1. 务存在很大的不确定性,不一定有访问压力
  2. 增加工作量,拖慢业务节奏

4. 分表

4.1 垂直分表

将一张表结构的多列拆到多张表(拆分不常用且占空间的列)

查询次数翻倍

4.2 水平分表

表的数据量达到千万级别,要考虑

  • 路由算法:

    • ID 范围

      1 ~ 999999 放到数据库 1 的表中;1000000 ~ 1999999 放到数据库 2 的表中

      可以随着数据的增加平滑地扩充新表;但是分布不均匀

    • Hash

      选取某个列的值哈希,分散到不同的数据库表中

      分布均匀;但是加表数据要重分布

    • 配置路由

      用一张独立的表来记录路由信息

      必须多查询一次,数据量太大路由表本身可能有性能问题

  • JOIN

    数据分散在多个表中,需要在业务代码或者数据库中间件中进行多次 JOIN 查询,然后将结果合并

  • COUNT()

    • COUNT() 相加

      在业务代码或者数据库中间件中对每个表进行 COUNT() 操作,然后将结果相加

      实现简单;性能低

    • 记录数表

      每次插入或者删除子表数据成功后,都更新对应记录数表

      性能好;可能数据不一致

  • ORDER BY

    业务代码或者数据库中间件分别查询每个子表中的数据,然后汇总进行排序