SQL - 慢 SQL

201 阅读3分钟

MySQL --log-slow-queries[=file_name] 选项启动时,mysqld 会写一个包含所有执行时间超过long_query_time 秒的 SQL 语句的日志文件,通过查看这个日志文件定位效率较低的 SQL

SQL优化原因:

查询效率低的SQL(慢SQL)会占用机器大量的CPU、内存和IO资源,影响正常业务。

慢SQL现象/影响:

SQL查询缓慢、业务超时、数据库机器CPU/IO飙升、业务连接不上数据库、现网故障等。

优化原则

优化总原则:业务侧优化 > SQL 优化 > 数据库+操作系统参数优化 SQL优化原则:高频SQL收益 > 低频SQL收益 业务侧优化例子: (1)某业务每隔1分钟会并发几十路去数据库查询A表(全表扫描),造成其他业务响应超时 (2)统计分析类SQL拆分,热点数据缓存

Optimizer查询优化器方式

逻辑优化 优化器的逻辑优化,即根据关系代数规则,对SQL语句进行等价变化: (1) 对投影、选择等操作进行句式优化; (2) 对条件表达式进行谓词优化、条件化简; (3) 对连接语义进行外连接、嵌套连接的优化; (4) 对集合、GROUP BY、ORDER BY等优化 (5) 子查询优化、视图重写、语义优化

逻辑优化例子 条件化简 :

select id,sfzh,address from t1 where 1=1 and name ='宸谦';

子查询优化 :

select * from t1 where a in (select a from t2);

优化器逻辑优化结果:

select t1.* from t1 join t2 on t1.a= t2.a;

Explain 查看执行计划

在SQL语句前加explain关键字可查看SQL语句的执行计划

常用语法:

(1)explain extended(输出更多扩展信息)

(2)explain format=json (json格式输出,可看到cost等信息)

优化步骤总结

  1. 查看执行计划 explain extended
  2. 如果有告警信息,查看告警信息 show warnings;
  3. 查看SQL涉及的表结构和索引信息
  4. 根据执行计划,思考可能的优化点
  5. 按照可能的优化点执行表结构变更、增加索引、SQL改写等操作
  6. 查看优化后的执行时间和执行计划
  7. 如果优化效果不明显,重复第四步操作

慢 SQL 常见问题

  1. where 条件索引列使用了 !=not in

select * from t where a != 1;

解决方案:

select * from t where a > 1 and a <1;
  1. 索引列函数转换,索引列参与计算

select * from t where date(a) = "2020-09-15";

解决方案:

索引列不存与计算和函数转换

select * from t where a = 1+1;
select * from t where a = date(`20200915`)
  1. 字段类型隐式转换,比如 a 为 varchar 类型

select * from t where a = 1;

解决方案:

where 条件字段类型保持一致

select * from t where a = '1';
  1. 表结构和索引设计不合理,复合索引中未使用前导列

复合索引(a,b,c) select * from t where b = 1 and c= 2;

解决方案:

索引尽量使用复合索引,并使用前导列,索引个数不超过 5 个

## 复合索引为(b,c,a)
select * from t where b =1 and c = 2;
  1. like /regexp % 匹配符在左边
select * from t where a like '%t%';

解决方案:

符合业务逻辑的情况下,修改为

select * from t where a like 't%';
  1. 大量数据分页问题

M >= 10000 select * from t limit M,N

解决方案:

改成基于主键查询

select * from t where id>= (select id from t limit M,1) limit N