文章目录

  • 前言
  • 一、慢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语句强制走索引;