MySQL not exists 与索引的关系

MySQL not exists 与索引的关系,第1张

概述MySQL not exists 与索引关系

在一些业务场景中,会使用NOT EXISTS语句确保返回数据不存在于特定集合,部分同事会发现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方式的执行计划:

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

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

@H_404_57@推荐看下:为什么索引能提高查询速度?

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

使用NOT EXIST方式的执行过程:

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

从执行过程来看,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子查询的执行次数即外层查询结果集的数据量。

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

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

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

京东商城也曾出现过大量类似案例,一些表使用VARCHAR来存放订单号,而另一些表使用BIGINT来存放,在两表进行管理时性能极差,希望研发同事引以为戒。关注公众号Java技术栈回复m36获取一份MysqL研发军规。

相关学习推荐:mysql视频教程

总结

以上是内存溢出为你收集整理的MySQL not exists 与索引的关系全部内容,希望文章能够帮你解决MySQL not exists 与索引的关系所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1151178.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)