前言:我们在日常开发中,或多或少都会遇到。某些表初期,查询速度非常快。但是,随着业务发展,数据量越来越多之后。SQL查询越来越慢的情况,那么基于这种情况,我们如何去:

  1. 发现慢SQL
  2. 治理慢SQL
  3. 规避慢SQL

1.慢SQL发现

  慢SQL的发现,我们可以使用MySQL自带的慢SQL监控日志,去获取系统中运行的慢SQL。
具体方法
my.cnf文件设置慢SQL监控级别

## 开启慢SQL监控日志
slow_query_log = ON
## 慢SQL日志生成地方,与文件名称
slow_query_log_file = /var/lib/mysql/VM-8-14-centos-slow.log
## 慢SQL监控阈值,此处为1秒,及大于一秒的日志都会被监控进 /var/lib/mysql/VM-8-14-centos-slow.log文件
long_query_time = 1

如图,监控日志里,会显示当前慢SQL执行时间Query_time,锁表时间Lock_time,执行扫描数据行数Rows_examined

mysql 监控查询延迟 mysql 慢sql 监控_SQL


当然,该方法。监控到的慢SQL,会非常的多,并且重复。所以,我们可以考虑使用慢SQL日志文件分析工具,进行分析常发生的慢SQL。

分析工具例如:mysqldumpslow、pt-query-digest,这里推荐使用pt-query-digest,该工具分析更加具体详细。

mysqldumpslow使用:mysqldumpslow pt-query-digest使用:pt-query-digest

2.慢SQL治理

  获取到具体的慢SQL后,我们就可以拿到,具体哪些微服务系统存在慢SQL问题。但是,拿到SQL后,我该从哪些维度入手去分析慢SQL的问题呢。

2.1 表中的数据量级别

2.1.1 表数据量,达到亿级别
  当表数据达到亿级别以上后,实际查询效率已经达到了MySQL的瓶颈。此时就需要考虑

  1. 历史数据是否可以分区归档(如按照数据的日期按年、月份分区),将历史不经常使用的数据进行分区处理,减少活跃数据量。分区方案:
  2. 当前单表新增数据量比较快,单月就能突破亿级别。此时,可以考虑直接对该表进行分区。分区得方法可以参考:通过MySQL函数完成分区、也可以手动使用范围、列表、hash手动创建表,通过代码逻辑控制分区
2.2 业务场景中SQL实际需求频率

2.2.1 调查慢SQL所在的实际业务场景
目的:针对弃用的功能,考虑停用业务场景。非弃用功能,在考虑索引使用情况。如索引使用正常,实际业务有需求,可以考虑读写分离,扩展读取的物理机器。

2.3 SQL的索引命中、性能情况

2.3.1 字段类型不匹配
字段类型不匹配:
情况一:使用字段类型不对应,如字段a为varchar类型,判断条件为 where a = 1,类型不匹配就可能会导致类型不匹配导致索引失效。
情况二:多表关联查询,关联查询的表字段,类型不匹配
2.3.2 函数或复杂运算导致类索引失效
2.3.3 MySQL实际使用索引扫描行数,不如直接走全表扫描的行数
情况一:判断条件索引列与order by或group by非同列,二次排序或分组操作,导致了索引失效。如表T存在a、b字段,索引构建为idx_a(a),实际sql为【where a = 1 order by b 】或 【where a = 1 group by b】,在从索引列获取数据后,因为需要二次回表进行排序或分组操作导致索引失效
情况二:数据量大时,因为左模糊或全模糊查询导致索引失效
情况三:多个or操作导致索引失效
情况四:不等于!= 或 is not 操作非条件判断导致索引失效

2.4 提升服务器硬件能力优化SQL执行效率

2.4.1 增加CPU核心数
目的:提升sum、count 计算型SQL 执行能力
2.4.2 增加内存大小
目的:扩大缓存空间大小,增加缓存命中率,降低回原表查询几率,提升速度。
2.4.3 普通硬盘存储介质切换为SSD高IO存储介质
目的:提升数据库读写的物理速度,当前 SSD 读写速度是普通磁盘的10倍左右。

3.如何避免慢SQL

避免慢SQL可以考虑从开发前如何避免与产生后如何发现治理考虑。
开发前:做表设计初期,就考虑到当前表唯一键是什么,后期执行时那些字段会是频繁查询字段,并指定合理索引。后期开发过程中,约束开发人员,尽量使用索引字段。
产生后:产生后则是,早监控,早治理。如设置慢SQL监控日志,并定期处理产生的慢SQL日志,早发现,早治理。