业务慢查询优化分享

159 阅读3分钟

explain里面一些字段信息

image.png

优化过程

以下是针对两个sql语句结合业务场景进行优化的案例

业务sql一

sql语句

SELECT distinct(target_id) FROM ap_user_privilege where expired_time > '2020-04-07 11:56:57';

业务背景

主站的评论区调用xuser接口获取up主的 的大航海数量,接口qps 4w+(但是大部分请求中的up主都没大航海船员),所以服务定时每秒获取当下拥有有效身份的大航海的主播id放在内存中,接口判断请求ID不在内存中直接返回,这一步挡住了大部分的请求

慢查询分析

image.png

ixtest是(target_id,expired_time)的联合索引,这里优化器选择使用联合索引ixtest,而where条件是按照expired_time进行搜索的,没有用到前导列 target_id,所以进行了索引扫描,造成效率低

慢查询优化

1.根据业务场景,sql语句写的是合理的,没有优化空间

2.索引实际用到了索引扫描,没用到索引查找,索引有优化空间

根据sql语句,可以使用对expired_time建立单索引(实际表已经建立了这个索引,但是优化器没有使用)

使用expired_time单索引,相比较使用联合索引扫描行数少了大概30%

image.png

image.png 优化之后的语句为

SELECT  distinct(target_id) FROM  ap_user_privilege  force index(expired_time) where expired_time > '2020-04-09 18:34:52';

20号上线之后慢查询已经没有了,问题解决

更好的方法:

目前强制使用单索引不会全索引扫描,但是会生成临时表,且需要回表,更好的办法是建立(expired_time,target_id)的联合索引,这样虽然还是会生成临时表,但是没有全索引扫描,不用回表,性能会大大提升

zhuanlan.zhihu.com/p/411359802

业务sql二

sql语句

SELECT id,skin_id,start_time,end_time,msg_status FROM ap_room_skin_config WHERE end_time <= '2020-04-07 12:09:00' OR start_time > '2020-04-07 12:09:00';

业务背景

获取所有失效的皮肤信息用来发送失效广播,每分钟执行一次

慢查询分析

1.全表扫描,没有使用索引

image.png

慢查询优化

语句优化

根据sql条件返回的数据几乎跟全表数据量相等,这样即使使用索引还是会hit到大部分索引范围,回表扫描大部分数据,所以应该在语句上优化

image.png

image.png 语句不合理的地方有几点

1.需求是获取所有当前过期的皮肤,但是查询的时候还用start_time 做判断条件,然后在业务里又去掉

2.获取截止到当前所有的过期皮肤,这样数据量会越来越大

优化的方法就是对过期时间做限制,查找两天内过期的皮肤,针对end_time做单索引

优化后的语句为

SELECT id,skin_id,start_time,end_time,msg_status FROM ap_room_skin_config WHERE end_time <= '2020-04-07 12:09:00' AND  end_time => '2020-04-05 12:09:00';

参考

www.cnblogs.com/kerrycode/p…

www.cnblogs.com/songwenjie/…

stackoverflow.com/questions/2…