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等信息)
优化步骤总结
- 查看执行计划 explain extended
- 如果有告警信息,查看告警信息 show warnings;
- 查看SQL涉及的表结构和索引信息
- 根据执行计划,思考可能的优化点
- 按照可能的优化点执行表结构变更、增加索引、SQL改写等操作
- 查看优化后的执行时间和执行计划
- 如果优化效果不明显,重复第四步操作
慢 SQL 常见问题
- where 条件索引列使用了
!=或not in
select * from t where a != 1;
解决方案:
select * from t where a > 1 and a <1;
- 索引列函数转换,索引列参与计算
select * from t where date(a) = "2020-09-15";
解决方案:
索引列不存与计算和函数转换
select * from t where a = 1+1;
select * from t where a = date(`20200915`)
- 字段类型隐式转换,比如 a 为 varchar 类型
select * from t where a = 1;
解决方案:
where 条件字段类型保持一致
select * from t where a = '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;
- like /regexp % 匹配符在左边
select * from t where a like '%t%';
解决方案:
符合业务逻辑的情况下,修改为
select * from t where a like 't%';
- 大量数据分页问题
M >= 10000 select * from t limit M,N
解决方案:
改成基于主键查询
select * from t where id>= (select id from t limit M,1) limit N