参考美团内部分享,原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和子查询。