大家有自己的思路就用自己的,如果没有学习一下深分页,,或者因为数据量,或者没有索引,按照这样的想法往下排查。
explain 分析sql的执行计划;
profile 分析执行耗时
Optimizer Trace分析详情
确定问题并采取相应的措施。
- 慢查询日志:
通过慢查询日志,来查看慢sql,默认mysql不开启的,需要手动开:
show query log
2.查看慢SQL的日志配置:show variables like 'show_query_log%'命令 。
我们可以看到对应的日志开启的状态,日志保存的目录, show variables like 'long_query_time'
查看超过多长时间才记录到慢查询日志。
3.通过日志定位哪些执行起来效率较低的sql语句,重点进行关注和分析。
explain 查看分析sql的执行计划
当我们定位效率低的sql的时候,就要进行explain 查看sql的执行计划,当explain 与sql一起使用时 MySQL将会显示来自 优化器 的有关语句执行计划的信息,即:mysql 解释了将如何处理该语句,包括有关如何连接表以及以何种顺序连接表等信息。
使用explain后,重点关注:type,rows filtered extra key.
type :表示连接类型,查看索引的执行情况的一个重要指标,以下性能从好到坏依次:system>const>eq_ref>ref>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>All
具体含义,可以自行查阅一下。
rows
该列表示mysql估算要找我们所需的记录,需要读取的行数,对于innoDB表,此数字是估算值,并非一定是个准确值。
filtered,自行查阅
key,自行查阅
- profile 分析执行耗时
expalin只是预估的执行计划,要真的sql执行状态和耗时,需要用profiling。开启profiling,后续执行sql语句都会记录其资源开销,包括IO,上下问切换,CPU内存,我们可以根据这些开销进一步分析
profiling 默认是关闭的,我们可以用 show variables like ‘%paorfil%’查看是否开启,如下:
可以用:set profiling=ON开启,开启后运行几条SQL 查看一下。
- Optimizer Trace 分析详情:
profile 只能看到sql的执行耗时间,但是无法看到SQL的真正执行过程,此时我们要使用 optimezer Trace 可以追踪sql的执行全过程。我们通过set optimizer_trace ='enabled=on' 打开开关,执行要追踪的sql ,最后执行 select * from information_schema.optimizer_trace 跟踪,如下:
确定问题并采取相应的措施:
- 多数慢sql都和索引有关系,比如不加索引,索引不生效,不合理,需要我们进一步优化索引。
- 优化sql语句:比如in使用太多,深分页问题,比如以前的进行时间段分查询。
- SQL没有很多的办法优化,可以采用es方式,或者数仓。
- 单表过大,进行分库分表。
- 数据量过大,是否考虑部分数据进行归档。
- 索引上使用了:is null和is not null索引可能失效
- order by 可能效率低
- 索引字段使用(! = 或者<>)索引可能失效。
- group by 使用不当会导致慢sql
- join或者子查询太多
- in元素过多
- 拿不到锁
注意点:delete+in子查询不走索引,select+in子查询,走索引。
SQL小技巧:
- select使用具体的字段,而不是*
- 在where 子句中不要用使用or
- 获取最新的就用limit 不要使用排序
- 字段类型尽量使用数值,而不是字符串,例如:0、1表示具体意思,而不是直接string值
- 批量操作(跟新,删除,查询)
- 少用union而是用union all
- 尽量使用not null定义字段
- 避免索引上使用 内置函数
- 尽量避免 在where子句中对字段进行表达式操作。
- 为了提高groupby 效率,执行语句前,把不需要的过滤掉
- 优化你的like语句
- in不能太多
- 优化limit分页
- 尽量使用连接查询而不是子查询
- 尽量避免在where中使用:<>!
- 使用联合索引注意索引的顺序
- 对查询进行优化,应考虑在where 及order by 涉及到表上建立索引,所以避免全表扫描
- 在适当时候使用,覆盖索引
- 删除 冗余和重复索引
- 不要有超过3个以上的表连接
- 索引不易太多,一般5个内
- 如果字段类型是字符串,where一定用引号括起来,不然索引失效 where ID=123,而是 where ID=‘123’
- 尽量少给客户端返回数据