一句sql引发的血案

瞧瞧sql

SELECT DISTINCT t1.Cd AS Cd, t1.Nm AS Nm, COUNT(t1.Id) AS count
FROM `table1` t1
LEFT JOIN `table2` t2 ON t1.Active_Id = t2._Active_Id
WHERE t2.Cls_Typ = 10100
AND t2.Sub_Typ = 20100
AND t1.BS_Flg = 10900
AND t1.crt_Tm BETWEEN '2019-06-24 00:00:00' AND '2019-08-29 23:59:59'
GROUP BY Cd
ORDER BY count DESC
LIMIT 3

sql的意思是通过连接表2,分组查询表1中满足条件的,出现最多的不重复的三个Cd
table1的数据量是20w+,table2的数据量也是20w+。

查询时间20s!!!

explain后的结果


image.png

显示了索引基本无效,全表查询,猛虎落泪。

起因

早晨为了去除脏数据上传了一版代码,当然这和以下要说是sql没关系。但是当时的我可不这么认为,问题出在再次发版后的半小时后。突然我们的app访问不上,作为一只小白这时候做了以下操作:
1.怀疑上传的代码有问题,仔细查了下git操作没任何问题。
2.再次查看域名访问没有成功,用ip去调用成功。
3.这时候怀疑是域名解析问题,运维查询无错。
4.换了不同的电脑尝试访问登陆接口login,时好时坏,因为有2台服务器,怀疑是负载均衡问题,换了另个查询接口A(好死不死就是慢查询接口)同上。
5.再次用两台服务器ip调用,还是时好时坏。
6.nginx重启。
7.打印pm2 日志,查到了类似于这样的输出。

PM2 | App name:xxx id:1 disconnected
PM2 | App [xxx] with id [1] and pid [16508], exited with code [0] via signal [SIGINT]
PM2 | Starting execution sequence in -cluster mode- for app name:xxx id:1
PM2 | App name:xxx id:1 online
 ———————————————— 
版权声明:本文为CSDN博主「FserSuN」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Revivedsun/article/details/79825185

看了下restart次数果然很高,但是pm2 delete 删除进程后,再次start却restart次数却并没有上升。越来越扑朔迷离。
8.换了个其他接口调用,发现居然可以,多个ip试了多次都可以。
9.开始在login打log,一步步查,查到没走通mysql数据库。
10.使用健康接口healthTrack,测试mysql数据库连接,花了4s才出结果。
11.删掉了healthTrack里测试redis的内容,居然变得很快,是不是觉得是redis问题了。
12.但是A接口并没有用到redis,想说试试把mysql重启了,重启无效。
13.运维查了下慢查询的sql,好巧不巧就是A接口的。
别问为啥会查慢查询,Java小伙伴让运维试的。

别问上线三天之前没出问题,很迷,应该是数据量每日叠加,耗时与数据量正相关。
测试环境没出现问题,也与数据量有关。

解决方案

舍弃mysql查询,放入redis,查询redis。

教训

需要全表查询连接,组合,计算的业务不适合数据量多的mysql,要考虑其他方式设置,如redis缓存。

你可能感兴趣的:(一句sql引发的血案)