问题描述:
有如下语句,执行(3613099/3600/24=41.8天)没结果
select dev,uname,ip from sdk_login_20170322 where pid=1 and gid =1002464 and dev in (
select dev from sdk_login_20170322 where pid=1 and gid = 1002464 group by dev having count(distinct uname) >= 20
执行计划如下:
原因分析:
mysql5.5在子查询方面存在不足。用到dependent subquery子查询,这个查询计划会先执行外面的查询,也即是先运行:select dev,uname,ip from sdk_login_20170322 where pid=1 and gid =1002464
这里会得到849041条记录,然后再拿每条记录去调用select dev from sdk_login_20170322 where pid=1 and gid = 1002464 group by dev having count(distinct uname) >= 20
也就是子查询会被执行84万次,这会导致查询无法得出结果。
解决办法:
(1)SQL改写,改写为如下的inner join子查询,执行时间只需要6秒不到。
select a.dev,a.uname,a.ip from sdk_login_20170322 a inner join (select dev from sdk_login_20170322 where pid=1 and gid = 1002464 group by dev having count(distinct uname) >= 20 ) b on a.dev=b.dev where a.pid=1 and a.gid=1002464 ;
执行计划是:
(2)先手工查出子查询的执行结果,再用in查询,也即运行两次查询,变成如下查询,2秒内产生结果。
改善建议:
(1)mysql 5.5以下,避免用子查询,如果要用,最好用desc看一下执行计划,避免执行计划中出现dependent subquery关健字;
(2)通常可以将dependent subquery子查询改写为inner join查询;
(3)增加对长select语句的监控,邮件报警,及时发现问题。
(原创连接:http://www.cnblogs.com/tonnyChen/p/6889940.html )