为了账号安全,请及时绑定邮箱和手机立即绑定

SQL优化案例--使用LEFT JOIN替换NOT EXISTS子查询

标签:
Java

事会发现NOT EXISTS有些场景性能较差,甚至有些网上谣言说”NOT EXISTS不走索引”,哪对于NOT EXISTS语句,我们如何优化呢?

========================================================##

以今天优化的SQL为例,优化前SQL为:

SELECT count(1)

FROM t_monitor m

WHERE NOT exists

(SELECT 1

FROM t_alarm_realtime AS a

WHERE a.resource_id=m.resource_id

AND a.resource_type=m.resource_type

AND a.monitor_name=m.monitor_name)

我们使用LEFT JOIN方式进行优化,优化后SQL为:

SELECT count(1)

FROM t_monitor m

LEFT JOIN t_alarm_realtime AS a

ON a.resource_id=m.resource_id

AND a.resource_type=m.resource_type

AND a.monitor_name=m.monitor_name

WHERE a.resource_id is NULL

优化效果:

优化前执行时间29秒以上,优化后1.2秒,优化提升25倍

========================================================##

哪NOT EXISTS真的不走索引么?查看两种SQL的执行计划:

使用NOT EXIST方式的执行计划:

webp

a.png

使用LEFT JOIN方式的执行计划:

webp

b.png

从执行计划来看,两个表都使用了索引,区别在于NOT EXISTS使用“DEPENDENT SUBQUERY”方式,而LEFT JOIN使用普通表关联的方式。

========================================================##

通过MySQL提供的Profiling方式来查看两种方式的执行过程

使用NOT EXIST方式的执行过程

webp

c.png

使用LEFT JOIN方式的执行过程:

webp

d.png

从执行过程来看,LEFT JOIN方式的主要消耗在Sending data一项上(1.2s),而NOT EXISTS方式主要消耗在executeing和Sending data两项上,受限于Profiling只存放100行记录缘故,从Profiling中只能看到47个” executeing和Sending data”的组合项(每个组合项约50us),通过执行计划看出,外表t_monitor的数据量为578436行,忽略统计信息不准情况下,使用NOT EXISTS方式应该会产生578436个” executeing和Sending data”的组合项,总计消耗时间=50μs*578436=28921800us=28.92s。

从上面执行过程可以推断出:

使用NOT EXISTS方式的执行性能严重依赖于NOT EXISTS子查询的执行次数即外层查询结果集的数据量。

1、 当外层查询结果集的数据量N较小时执行性能较好,如有N=10执行时间为50μs*10=500us=0.005s,再加上一些额外消耗,执行结果也能在0.01秒或10毫秒内范围,这个响应时间应该能被大部分应用程序接受。

2、 当外层程勋结果集的数据量N较大甚至上千万数据量时,NOT EXISTS的查询性能会变得非常糟糕,甚至会大量消耗服务器IO和CPU资源从而影响其他业务正常运行。

除上述问题外,在优化过程中发现本应该存储相同数据的resource_id列在两个表中定义不同,一表为VARCHAR而另外一表为BIGINT,外部结果集的字段类型和NOT EXIST字表中字段类型不同导致NOT EXISTS子查询中无法使用索引,使得子查询性能较差,最终影响整个查询的执行性能。



作者:Ferrari1001
链接:https://www.jianshu.com/p/9f10e5e90155


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消