1.如何定位慢查询
方案1:开源工具
调式工具:Arthas
运维工具:Prometheus、Skywalking
方案2:MySQL自带慢日志
慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。
如果需要开启慢查询的日志,需要在MySQL的配置文件(my.cnf)中配置如下信息:
2.如何分析慢查询
使用EXPLAIN或者DESC命令获取MySQL如何执行SELECT语句的信息
- 通过key和key_len检查是否命中了索引(索引本身存在是否有效的情况)
- 通过type字段查看sql是否有进一步优化的空间,是否存在全索引扫描或全盘扫描
- 通过extra建议判断,是否出现了回表的情况,如果出现了,可以尝试添加索引或修改返回字段来修复
type 列
性能由好到差为:NULL、system、const、eq_ref、ref、range、index、all
- NULL: 表示没有查询表
- system: 表示查询的MySQL自带的表数据
- const: 表示通过索引只能匹配到一行数据。 explain select * from student where id = 1688
- eq_ref: 表示使用了等值连接(例如,使用主键或唯一索引连接表)。explain SELECT * FROM student s1 JOIN student s2 ON s1.id = s2.id WHERE s1.age = 25;
- ref: 表示使用了非唯一索引进行查找,并返回匹配的多行或一行数据。 explain select * from student where name = '张68'
- range: 表示使用了索引进行范围查找,例如使用比较符(>, <, BETWEEN)或IN操作符。 explain select * from student where age < 1688
- index: 表示全索引扫描,也就是说用了某一个索引的全部, 通常发生在查询使用索引覆盖的情况下。explain select count(*) from student ;explain select sum(age) from student
- all: 表示全表扫描,即没有使用索引,需要遍历整个表进行查询。 explain select * from student
Extra列
3.可能出现SQL慢的情况
1、避免使用select *
通过explain查看执行计划,select *走的是全表扫描,没有用到任何索引,查询效率是非常低的;
*中得字段如果包括索引之外的字段,那么就会走回表查询(聚簇索引和非聚簇索引),这样一来效率就会非常慢;
另外有一些字段比文本类型,大字段数据传输也会增加网络消耗,所以杜绝使用select * 是常见优化方式之一。
2、小表驱动大表
小表驱动大表是指数据量较小,索引比较完善的表,然后使用其索引和条件对大表进行数据筛选,从而减少数据计算量,提高查询效率。
3、连接查询代替子查询
子查询需要执行两次查询数据库,一次是外部查询,一次是嵌套子查询。因此,使用连接查询可以减少数据库的查询次数,提高查询的效率。
对于大型数据集,使用连接查询的效率通常比子查询更加高效,子查询通常是需要扫描整个表,而连接查询可以利用索引加速读取操作
4、提升group by的效率
创建索引:如果你使用group by的列没有索引,那么查询可能会变得很慢。因此可以创建一个或者多个索引,来加速查询效率
5、批量操作
循环插入肯定效率是最低的,因为需要和数据库进行多次交互,损耗性能,因此可以采用通过动态sql的方式对sql进行批量插入(默认是没有开启的,需要在配置中开启)
注意:虽然动态sql可以大大提升插入的效率,但是不建议一次性插入太多的数据。因为数据太多的话数据库响应也会很慢。批量操作需要把我一个度,一般建议每次插入的数量500.然后分批次处理。这个样也可以很好的避免内存溢出(数据太多内存不够)或者死锁等问题。
6、使用limit
如果一次查询的数据太多的话,一个查询返回上万条数据,不仅占用了大量的系统资源,也会占用更多的网络宽带,影响查询效率。使用limit可以限制返回数据的行数,减轻系统负担,提升查询效率。
7、join的表不宜过多
多表join的话查询数据对比时间表较长
join需要经过大量的计算,会导致系统负载增加
维护难度较大,如果一条查询的sql连接表比较多,那么如果后期需要修改其中一个表的结构和内容,很可能需要同时修改其他表的结构和内容