在日常工作当中,数据库的查询SQL占比要比写入高很多。当业务数据量增长到一定阶段时,我们难免会碰到数据库查询慢的问题。那知道如何快速定位慢SQL并理清楚排查方案便成为了解决此类问题的关键所在。
所以,SQL慢查询性能排查在面试中经常会被问到也就不足为奇,老王这里根据自己的过往排查经验给大家分享一些心得体会,希望对大家面试和工作中有所帮助。
1、如何界定是慢查询SQL
我们知道MySQL 的慢查询日志,是用来记录在 MySQL 中响应时间超过阀值的语句,这个值指的就是运行时间超过 long_query_time 值的 SQL,则会被记录到慢查询日志中。long_query_time 的默认值为 10。比如,我们自定义值为100ms, 如果有SQL查询超过了这个值,就认为是超出了我们所能接受的时间范围。那这种语句即可定义问慢SQL。
2、如何快速定位低效率SQL
1)查看慢SQL语句
slow_query_log: 这个参数设置为ON,可以捕获执行时间超过一定数值的SQL语句。当然,在很多大企业,都有专门DBA管理这部分内容,研发侧通过订阅形式会定期统一排查慢SQL语句。而在一些中小企业,就需要DBA或者是研发自己手动查询哪些是慢SQL然后行分析。
2)查询超过某个时间值的SQL语句
long_query_time:当SQL语句执行时间超过此数值时,就会被记录到日志中,建议设置为1秒或者更短。这个需要结合实际的业务场景,如果应用业务对时间要求比较高,那可以设计的短一些,比如100~300ms。否则可以设置的打一下,比如,类似于报表导出这种查询。
3)查询记录日志的文件名
slow_query_log_file:记录日志的文件名。这个操作对于查询历史慢SQL比较方便。
4)查询未使用索引的SQL语句
log_queries_not_using_indexes:这个参数设置为ON,可以捕获到所有未使用索引的SQL语句。这部分往往也是性能优化的关键所在,可辅助我们快速了解问题所在。
3、慢查询优化基本步骤
- 首先拿到慢SQL,运行确认是否真的很慢。建议设置SQL_NO_CACHE, 否则因缓存效果很难判断真的慢。
2)识别表查询字段区分度。这部分也是在排查过程当中比较不好排查的一个问题点。比如我们常常使用的枚举值,0和1。这种区分度很低的类型,如果应用在索引上,可能对查询效果提升不是很明显。
此时,我们可以通过Where条件单表查询。分别对单表的每个字段进行查询,看哪个字段的区分度最高。此时我们可以对该字段进行设定索引。
-
通过Explain查看SQL执行计划,是否与预期一致。
-
当SQL中使用了Order by Limit 这种形式,可以让排序的表优先查。
-
如果识别出有些查询字段未加索引,可以参照建索引的几大原则。
-
如果排查完后,确认不是sql本身慢的问题,此时我们需要回归到业务上,了解业务方使用场景。比如通过调整业务处理逻辑来提升查询性能,如串行改并行、增加缓存等方式。
4、慢SQL优化的一些基本原则
1)*号问题
查询时,不要用*号,尽量写全字段名。
2)尽量避免子查询嵌套
大部分情况连接效率远大于子查询。
3)善于利用MySQL分析工具
A、多使用explain和profile分析查询语句
B、用命令slow_query_log查看慢查询日志,找出执行时间长的sql语句优化
4) 小表join大表的场景
多表连接时,尽量小表驱动大表,即小表 join 大表。
5)分页查询
在千万级数据量机械能分页时,注意使用limit提升效率。
6)考虑缓存
如果业务查询对数据时效性要求不是很敏感,可以对于经常使用的查询SQL开启缓存。
通过以上四个步骤,可以帮助我们快速发现那些执行时间特别长的SQL 查询,并且有针对性地进行优化,从而提高系统的整体效率。