• (原创)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 )

     

  • 相关阅读:
    从IRP说起(转)
    IoSkipCurrentIrpStackLocation .(转)
    IO_REMOVE_LOCK使用方法小结(转载加改正)
    TCP释放连接时为什么time_wait状态必须等待2MSL时间
    网络编程之select
    Ubuntu18.04 安装Chrome浏览器
    Ubuntu修改系统时间
    Linux常用命令总结
    struct ifconf和struct ifreq,获取网线插入状态
    一个简单的客户单与服务端程序
  • 原文地址:https://www.cnblogs.com/tonnyChen/p/6889940.html
Copyright © 2020-2023  润新知