数据库优化

Aug 31, 2016


参考美团内部分享,原ppt作者:房晓乐

一、优化相关概念

  优化,首先要明确我们需要优化什么,数据库优化其实主要就是优化性能、响应时间和吞吐量。

  • 性能:衡量完成特定任务的速度或者效率。
  • 相应时间:衡量系统与用户交互时多久能够收到响应。
  • 吞吐量:衡量系统在单位时间里可以完成的任务量。

  一些内部数据制作的图表不方便贴出来,直接总结下规律吧。对于每个系统,都会有自己的瓶颈,目前我们的瓶颈远远高于业务量,所以还不用太担心。所谓瓶颈,就是指QPS到达一个特定量级后继续增加,系统的整体性能会迅速下降。
  优化时有一些原则需要注意:

  • 不要访问任何不必要的数据。(select * 不可取)
  • 合理利用硬件来提升访问效率。
    • 使用缓存消除对数据的重复访问。
    • 使用批量处理来减少交互次数。
    • 使用新硬件来降低后端延时,提高效率。
  • 提高系统吞吐量
    • 对工作单元进行细化,减少串行操作。
    • 合理的拆分(先垂直拆分再水平拆分)以提高系统的整体吞吐能力。

  说了这么多,那么具体的优化步骤是什么呢?优化的原则是自上而下的,包括以下步骤:

  • 数据库schema设计
  • 应用连接:请求次数、网络交互、批量处理、连接管理
  • 数据库优化:SQL Parse、SQL Tuning、Locks、Concurrency
  • 实例参数配置:buffer_pool、innodb_flush_log_at_trx_commit
  • 存储引擎设置
  • IO配置

二、schema设计

  提到schema设计,肯定避不开范式,简单回顾下范式:

  • 第一范式:属性不能再细分,最基本的要求也比较好理解。
  • 第二范式:表中属性必须依赖全部主属性,而不是只依赖部分主属性。
  • 第三范式:表中非主属性之间不能有相互依赖。
  • BC范式:每个表中只有一个候选键(每一项都不同的键,比如自增ID)。

  达到BC范式的级别,一般就认为是设计比较良好的数据库啦。范式的优点不言自明,但是如果过度设计,反而会给系统带来瓶颈。schema设计要遵循以下原则:

  • 根据业务需求灵活的选择范式(轻范式、轻约束)
  • 数据类型在满足需求的情况下越小越好。
  • 动静分离、冷热分离、重要程度分离。
  • 使用自增主键。
  • 模式规范(sql编写规范等)

三、SQL优化

  执行计划:

  • 表关联:嵌套循环算法及优缺点
  • 驱动表:
    • 选择小结果集作为驱动
    • 子查询
    • 外链接
  • 数据访问:全表扫描、聚簇表及堆表、索引

  数据寻址-索引

  • 索引类型:
    • b+Tree索引
    • hash索引
    • 全文索引
    • R-Tree索引
  • 索引扫描方式:
    • 唯一扫描
    • 范围扫描
    • 跳跃扫描
    • 全扫描
    • 覆盖扫描

  索引总结:

  • 字段选择:
    • 主键要尽量短,辅助索引会使用主键,避免多联合字段创建主键。
    • 给索引的字段设置默认值。
    • 不要让含NULL的字段进入组合索引。
    • 删除过滤性低的字段的索引,可能性能更差。
    • 不能再索引字段上做运算,会失效。
    • 避免频繁更新的字段进入索引,增加IO负担。
    • 尽量覆盖索引(MySQL)排序效率不高。
  • 顺序选择:
    • 过滤性越高的字段需要越靠前。
    • 不干扰过滤前提下,排序字段进入索引。
    • 多SQL综合考虑,重复利用索引。
  • 索引维护:
    • 定期维护(重建)表上的索引(注意时间选择,会锁表)。
    • 注意索引的使用情况,及统计信息。

  执行计划总结:

  • 减少表连接,减少复杂SQL,拆分简单SQL。
  • 减少排序:非必要不排序,利用索引排序,减少参与排序的记录数,子查询避免排序。
  • 尽量减少select * 。
  • 尽量用join代替子查询。
  • 尽量少使用or,使用in或者union(union all)代替。
  • 尽量用union all 代替union。
  • 尽量早的将无用数据过滤:选择更优的索引,先分页在Join。
  • 避免类型转换:索引失效。
  • 优先处理高并发的SQL。
  • 三思而行,先看执行计划,再执行。

四、SQL优化思路和原则

  • 优化更需要优化query。
  • 从explain入手。
  • 多使用profile。
  • 小结果集驱动大结果集。
  • 只提取自己需要的column。
  • 尽量避免复杂的join和子查询。