关于DEPENDENT SUBQUERY的优化

正文

有一个条件查询同步的SQL,内容如下:

1
update naxxramas_coreapp_status a set a.post_num = (select count(b.publish_id) from naxxramas_app_publish b where b.app_name=a.app_name and b.env_type = 'production' and b.status = 'SUCCESS' and DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(b.gmt_end) GROUP BY b.app_name) where exists (select null from naxxramas_app_publish b where b.app_name=a.app_name)

这个语句比较简单,主要就是把naxxramas_coreapp_status这个表里的post_num字段更新成naxxramas_app_publish这个表里的符合条件的publish_id的个数。但是这个SQL却执行失败,原因如图:

可见是SQL语句执行时间过长,需要优化,explain一下看一下结果,发现有

这个Dependent Subquery是啥?官方含义为:

1
2
SUBQUERY:子查询中的第一个SELECT
DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询。

结合这个例子来说,就是子查询对b表的查询方式依赖于外层表a的查询,从explain的结果看,意味着这三步都走完,需要查询3751乘以36471乘以36471乘以0.01这么多行,不慢才怪呢。

这里补充一下,filtered是啥意思,它的意思是符合某条件的记录数百分比。其实只要执行两条sql语句,一条有where,一条无where,就可以看出filtered的作用。

最后优化的结果如下:

1
2
3
4
5
update naxxramas_coreapp_status a 
inner join
(select count(publish_id) as num,app_name FROM naxxramas_app_publish WHERE env_type = 'production' and status = 'SUCCESS' and DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(gmt_end) GROUP BY app_name) b
on a.app_name=b.app_name
set a.post_num = b.num;

效果如图:

再次explain一下看看:

这里我主要是“使用连接查询+放弃了判断b表、a表是否有各自不存在的记录”,而且没有触发子查询,可以从执行计划中看到执行计划已经从DEPENDENT SUBQUERY变成了DERIVED,以驱动表去关联查询了,没有完全的扫描行,这省去了较多的IO。

参考资料

https://blog.csdn.net/kk185800961/article/details/49340589
https://juejin.cn/post/6844904007228456974

感谢您请我喝咖啡~O(∩_∩)O,如果要联系请直接发我邮箱chenx1242@163.com,我会回复你的
-------------本文结束感谢您的阅读-------------