文章目录
- 前言
- 一、慢SQL?
- 1.记录遇到的问题
- 总结
前言
本文记录下今日在公司的慢SQL的优化,及遇到的问题
一、慢SQL?
慢SQL说大白话就是:执行耗时较久的SQL;
慢SQL会给程序带来较大的影响,会使线程阻塞在该状态,等待返回结果;
如果是提供的dubbo接口,对于异步接口,调用方不会受到太大影响,但在同步接口中,接口处理请求太久,程序还有可能调用接口超时异常,所以在我们的开发生产中我们应该尽量避免慢SQL的产生,或者减少SQL的执行耗时。
1.记录遇到的问题
这次是给公司内的其他系统提供的dubbo接口,遇到了慢SQL,直接导致dubbo超时,使别的系统该业务无法完成。
上菜(模拟SQL)
select (所查字段) from t_cap_repay_plan_detail
WHERE (联合索引的字段,顺序也复合)
order by id asc limit ?,?
这是已经在生产上跑了一段时间的SQL代码了,为什么这次突然冒出慢SQL呢?查看了之前的调用记录该SQL执行不慢,平均耗时在200毫秒左右,这次却执行了5+秒;
然后将该SQL放到测试环境使用explain解析该SQL,执行结果显示是会走索引的,所以当时觉得走索引的话生产不应该这么慢!
为了验证,我写好SQL去运维执行SQL,将值设为当时线上跑的数据,展现最真实的状态,执行之后在那条语句的确不走索引,而且索引在表里,没有被删除!
为了继续验证,我将具体数值设置为之前线上跑的值,线上使用explain解析SQL,却是走索引的,速度很快;
查询了相关资料,最终导致同一SQL的不同赋值,会有不同的走索引的情况是因为mysql会根据当前数据库的具体数据的,来决定走不走索引。
而让执行器决定不走索引的罪魁祸首的是
order by id asc
语句!
最后在确保走索引的情况下,平均耗时200毫秒,我将SQL
优化成以下格式:
SELECT
(所查字段)
FROM
t_cap_repay_plan_detail a
JOIN (
SELECT id FROM t_cap_repay_plan_detail WHERE (联合索引的字段,顺序也复合)
) b ON b.id = a.id
ORDER BY
a.id ASC
LIMIT ?,?
目的是将原本的SQL拆成两段嵌套式SQL,这样子查询就会走索引,而外层的查询排列也能使用ID排列;
总结
在where条件复合联合索引或联合索引的规则的情况下,order by可能会影响你走不走索引,在有较大可能影响的情况下,强烈建议将SQL改造成两段嵌套式的SQL查询,或者可以使用force index语句强制走索引;