(原创)dependent subquery 子查询改写

问题描述:

  有如下语句,执行(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 )

 

原文地址:https://www.cnblogs.com/tonnyChen/p/6889940.html