MySQL,一条两层subquery的坑爹优化

最近整一些见不得人的事情,每天都忙到很晚。悲剧。

 

 

 

SELECT a.client_id,
       s.cnt s_cnt,
       a.cnt a_cnt,
       s.cnt / a.cnt s_rate
FROM (SELECT COUNT(*) cnt,
             handle_client client_id
      FROM tb_captcha cpout
      WHERE expire_time > curdate ()
      GROUP BY handle_client) a 
     LEFT JOIN (SELECT COUNT(*),
       handle_client
FROM tb_captcha
WHERE id IN (SELECT MAX(id)
             FROM tb_captcha
             WHERE task_id IN (SELECT task_id
                               FROM tb_client_task_log
                               WHERE task_code IN ('registerRobotUserEmail','registerWeibo')
                               AND   status = 0
                               AND   executed_time > '2011-03')
             GROUP BY task_id,
                      seq)
GROUP BY handle_client;) s ON a.client_id = s.client_id
ORDER BY s.cnt DESC;

 

同事写了个子查询,跑到mysql上乖乖停不下来,最后被我kill掉了。

 

哥来优化一下。

 

先建索引

在tb_captcha建索引(expire_time, handle_client), (task_id)

在tb_client_log上建索引(status, execuited_time)

 

subquery很坑爹当成exists跑。都是all scan。



查询后的的数据量太大,type为all

 

怎么改呢。

1.如果临时表不是很大,用临时表ok

2.用join代替子查询

 

用inner join优化最里面的子查询。


可以看到里层已经将unique_dependency+all 优化成ref+range。测试性能有所提高,但是没有达到数量级的提高。大概提高了4,5倍。外面那个子查询还会将整个查询死掉。外面有个index type。

 

外部子查询用临时表优化

 


因为临时表都会比较小,所以这种方式对性能有很大的提高。

原来结果根本出不来。现在的执行时间是:

 


执行时间是10ms。

 

 

呵呵。应该算成功优化了。

 

再加上left join。

 


10ms。ok。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值