正文
有一个条件查询同步的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
2SUBQUERY:子查询中的第一个SELECT,
DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询。
结合这个例子来说,就是子查询对b表的查询方式依赖于外层表a的查询,从explain
的结果看,意味着这三步都走完,需要查询3751乘以36471乘以36471乘以0.01这么多行,不慢才怪呢。
这里补充一下,filtered
是啥意思,它的意思是符合某条件的记录数百分比。其实只要执行两条sql语句,一条有where
,一条无where
,就可以看出filtered
的作用。
最后优化的结果如下:
1
2
3
4
5update 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