NOT EXISTS真的不走索引么?如何优化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使用普通表关联的方式。
##========================================================##
通过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来存放,在两表进行管理时性能极差,希望研发同事引以为戒。
NOT EXISTS真的不走索引么?如何优化NOT EXISTS!相关推荐
- MySQL not exists 真的不走索引么?
在一些业务场景中,会使用NOT EXISTS语句确保返回数据不存在于特定集合,部分同事会发现NOT EXISTS有些场景性能较差,甚至有些网上谣言说"NOT EXISTS不走索引" ...
- MySQL is null真的不走索引吗?
MySQL版本5.7 建表 create table staffs( id int primary key auto_increment, name varchar(24) not null defa ...
- oracle查询sql走索引吗,Oracle SQL不走索引小记
sql执行计划不走索引 一.优化器认为走全表扫描更优. 在这种情况下,需要重新分析一遍表,更新表的状态,有助于优化器分析出正确的执行计划. analyze table tablename comput ...
- oracle不等于怎么走索引,oracle为什么不走索引
ename from tb2 where empno=7934;--还是不走index 真不懂了,难道只是因为我的优化器是CBO吗? 或者是因为统计信息没有刷新吗? 或者莫非是因为我的表因为是翻起来的 ...
- oracle 不走索引的原因
oracle 不走索引的原因 2013-02-01 13:46 9098人阅读 评论(0) 收藏 举报 分类: oracle(27) create table tb2 as select ...
- 一直认为in,exists 不走索引,被同事鄙视了……
前言 最近,有一个业务需求,给我一份数据 A ,把它在数据库 B 中存在,而又比 A 多出的部分算出来.由于数据比较杂乱,我这里简化模型. 然后就会发现,我去,这不就是 not in ,not exi ...
- oracle 优化器 失效,oracle 优化器 不走索引原因
SQL优化器简介 基于规则的优化器 .总是使用索引 .总是从驱动表开始(from子句最右边的表) .只有在不可避免的情况下,才使用全表扫描 .任何索引都可以 基于成本的优化器 .需要表.索引的统计资料 ...
- Mysql优化,导致查询不走索引的原因总结
原文地址:http://blog.csdn.net/m0_37808356/article/details/72526687 最近公司让我做SQL优化的工作(MySql),用explain发了一些问题 ...
- 带时间锉字段查询不走索引优化记录!+数据库卡顿问题排查顺序
近期解决了病历系统数据库卡顿的问题,以下为分析经过,本文重点为带时间锉字段的优化和数据库卡顿问题排查的思路! 郑州病历系统登录卡慢问题,初步看是体温单表(t_vital_signs)查询没走索引影响的 ...
最新文章
- 后台ajax调用中字符串到jquery中的json对象和数组对象转换问题
- 牛客网华为机试题 字符串问题 记录
- anki 插入表格_anki|建造师选择题制作的方法
- AB1601 PWM注意事项
- CF1063F-String Journey【SAM,线段树】
- 告毕业生书——七剑送你下天山
- android 调用百度sdk后运行不了,解决android程序中oncreate方法中调用百度地图MKSearchListener接口不执行的问题...
- PC端与虚拟机内容拷贝
- Atitit.iso格式蓝光 BDMV 结构说明
- Ubuntu 设置 samba共享文件夹
- hdu5294Tricks Device 最大流之最小割
- 2017 谷歌 I/O大会
- Java音频格式转换,支持amr、aud、slk、silk转成mp3的程序
- 一文看尽 6篇 CVPR2021 2D 异常检测论文
- Not Assigning
- 8个有用的表单构建工具,你一定要使用并收藏好
- 编码、学习、玩耍一条龙,这是我看过最良心的「游戏编程」网站,没有之一!...
- oracle在表上创建分区,Oracle分区表 (Partition Table) 的创建及管理
- eclipse中的javaEE插件
- 一坑未平一坑又起——圆锥曲线1-1 椭圆的定义中的东西