in和exists以及not in 和not exists有什么不同?(笔记)
来源:SegmentFault
2023-02-17 14:40:12
0浏览
收藏
来到golang学习网的大家,相信都是编程学习爱好者,希望在这里学习数据库相关编程知识。下面本篇文章就来带大家聊聊《in和exists以及not in 和not exists有什么不同?(笔记)》,介绍一下MySQL,希望对大家的知识积累有所帮助,助力实战开发!
exists 和 in
1.原理
通过使用EXISTS,Oracle会首先检查主查询,然后运行子查询直到它找到第一个匹配项, 这就节省了时间。Oracle在执行IN子查询时,首先执行子查询,并将获得的结果列表存放在一 个加了索引的临时表中。在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放 在临时表中以后再执行主查询。这也就是使用EXISTS比使用IN通常查询速度快的原因。
2.分析
in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内 表进行查询not exists:做NL,对子查询先查,有个虚表,有确定值,所以就算子查询有NULL 最终也有值返回not in:做hash,对子查询表建立内存数组,用外表匹配,那子查询要是有 NULL那外表没的匹配最终无值返回。一直以来认为exists比in效率高的说法是不准确的。
但是,如果查询的两个表大小相当,那么用in和exists差别不大。
3.总结
外表大,用IN;内表大,用EXISTS。
4.效率
- select * from T1 where exists(select 1 from T2 where T1.a=T2.a) ; T1数据量小而T2数据量非常大时,T1>T2 时,2) 的查询效率高。
5.举例说明
例如:表A(小表),表B(大表) 1: select * from A where cc in (select cc from B) 效率低,用到了A表上cc列的索引; select * from A where exists(select cc from B where cc=A.cc) 效率高,用到了B表上cc列的索引。 2. select * from B where cc in (select cc from A) 效率高,用到了B表上cc列的索引; select * from B where exists(select cc from A where cc=B.cc) 效率低,用到了A表上cc列的索引。
not in 和not exists
如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而 not extsts的子查询依然能用到表上的索引。 所以无论那个表大,用not exists都比not in要快。一直听到的都是说尽量 用exists不要用in,因为exists只判断存在而in需要对比值,所以exists比较快, 但其实根本不是这么回事。
示例:
select * from T1 where x in ( select y from T2 ) 执行的过程相当于: select * from t1, ( select distinct y from t2 ) t2 where t1.x = t2.y; 而使用exists select * from t1 where exists ( select null from t2 where y = x ) 执行的过程相当于: for x in ( select * from t1 ) loop if ( exists ( select null from t2 where y = x.x ) then OUTPUT THE RECORD end if end loop
in的方式比较直观,exists则有些绕,而且in可以用于各种子查询,而exists好像 只用于关联子查询(其他子查询当然也可以用,可惜没意义)。 由于exists是用loop的 方式,所以,循环的次数对于exists影响最大,所以,外表要记录数少,内表就无所谓了, 而in用的是hash join,所以内表如果小,整个查询的范围都会很小,如果内表很大,外表 如果也很大就很慢了,这时候exists才真正的会快过in的方式。 如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。 也 就是说,in和exists需要具体情况具体分析,not in和not exists就不用分析了,尽量用 not exists就好了。
典型的连接类型共有3种:
排序 - - 合并连接(Sort Merge Join (SMJ) ) 嵌套循环(Nested Loops (NL) ) 哈希连接(Hash Join)
嵌套循环和哈希连接的算法还是有不同,在理论上哈希连接要快过排序和nl,当然实际 情况比理论上有复杂的多,不过两者还是有差异的.
1 关联子查询与非关联子查询
关联子查询需要在内部引用外部表,而非关联子查询不要引用外部表。对于父查询中处理 的记录来说,一个关联子查询是每行计算一次,然而一个非关联子查询只会执行一次,而且结 果集被保存在内存中(如果结果集比较小),或者放在一张oracle临时数据段中(如果结果集 比较大)。一个“标量”子查询是一个非关联子查询,返回唯一记录。如果子查询仅仅返回一个 记录,那么oracle优化器会将结果缩减为一个常量,而且这个子查询只会执行一次。 select from emp where deptno in (select deptno from dept where dept_name=’admin’);
2. 如何选择?
根据外部查询,以及子查询本身所返回的记录的数目。如果两种查询返回的结果是相同 的,哪一个效率更好? 关联子查询的系统开销:对于返回到外层查询的记录来说,子查询会每次执行一次。因 此,必须保证任何可能的时候子查询都要使用索引。非关联子查询的系统开销:子查询只会 执行一次,而且结果集通常是排好序的,并保存在临时数据段中,其中每一个记录在返回时 都会被父级查询引用,在子查询返回大量记录的情况下,将这些结果集排序回增大系统的开 销。 所以:如果父查询只返回较少的记录,那么再次执行子查询的开销不会非常大,如果返 回很多数据行,那么直查询就会执行很多次。 如果子查询返回较少的记录,那么为内存中 保存父查询的结果集的系统开销不会非常大,如果子查询返回多行,那么需要将结果放在临 时段上,然后对数据段排序,以便为负查询中的每个记录服务。
3.结论
- 在使用一个关联子查询是,使用in 或者 exists子句的子查询执行计划通常都相同
- exists子句通常不适于子查询
- 在外部查询返回相对较少记录时,关联子查询比非关联子查询执行得要更快。
- 如果子查询中只有少量的记录,则非关联子查询会比关联子查询执行得更快。
4 子查询转化:子查询可以转化为标准连接操作
- 使用in的非关联子查询(子查询唯一) 条件:1.在整个层次结构中最底层数据表上定义唯一主键的数据列存在于子查询的 select列表中 2.至少有个定义了唯一主键的数据列在select列表中,而且定义唯一主键的 其他数据列都必须有指定的相等标准,不管是直接指定,还是间接指定。 - 使用exists子句的关联子查询 条件:对于相关条件来说,该子查询只能返回一个记录。
5. not in和not exists调整
- not in 非关联子查询:转化为in写法下的minus子句 - not exists关联子查询:这种类型的反连接操作会为外部查询中每一个记录进行 内部查询,除了不满足子查询中where条件的内部数据表以外,他会过滤掉所有记 录。 可以重写:在一个等值连接中指定外部链接条件,然后添加 select distinct ... from a,b where a.col1 = b.col1(+) and b.col1 is null
6. 在子查询中使用all any
原文地址
如果有侵权,马上删除
今天关于《in和exists以及not in 和not exists有什么不同?(笔记)》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于mysql的内容请关注golang学习网公众号!
版本声明
本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除

- 上一篇
- 分享一下我的 vue + koa + mysql 搭建博客之旅

- 下一篇
- Mysql锁机制介绍
评论列表
-
- 忧伤的蜜粉
- 这篇文章出现的刚刚好,师傅加油!
- 2023-04-01 01:03:45
-
- 健壮的身影
- 感谢大佬分享,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢师傅分享技术文章!
- 2023-03-30 17:54:42
-
- 合适的春天
- 这篇文章内容真是及时雨啊,细节满满,很棒,码住,关注老哥了!希望老哥能多写数据库相关的文章。
- 2023-03-08 07:57:18
-
- 积极的草丛
- 太全面了,码起来,感谢博主的这篇文章内容,我会继续支持!
- 2023-02-26 00:21:10
查看更多
最新文章
-
- 数据库 · MySQL | 2小时前 |
- MySQL数据库管理员必备的30个常用命令整理
- 319浏览 收藏
-
- 数据库 · MySQL | 2小时前 |
- MySQL主外键这样用!主外键关联关系超详解
- 259浏览 收藏
-
- 数据库 · MySQL | 3小时前 | MySQL字段注释 数据字典 数据库文档 COMMENT关键字 information_schema.COLUMNS
- MySQL设置字段注释超详细教程|快速搞定数据字典与字段说明
- 149浏览 收藏
-
- 数据库 · MySQL | 3小时前 |
- MySQL主键和唯一键傻傻分不清?主键选这个就对了!
- 500浏览 收藏
-
- 数据库 · MySQL | 4小时前 |
- MySQL改中文语言包,超详细配置教程来了!
- 304浏览 收藏
-
- 数据库 · MySQL | 5小时前 |
- MySQL缓存怎么设置?查询缓存到底香不香?
- 241浏览 收藏
-
- 数据库 · MySQL | 6小时前 |
- MySQL缓存设置教程,手把手教你优化参数,提速不是梦!
- 110浏览 收藏
查看更多
课程推荐
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
查看更多
AI推荐
-
- 茅茅虫AIGC检测
- 茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
- 93次使用
-
- 赛林匹克平台(Challympics)
- 探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
- 100次使用
-
- 笔格AIPPT
- SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
- 105次使用
-
- 稿定PPT
- 告别PPT制作难题!稿定PPT提供海量模板、AI智能生成、在线协作,助您轻松制作专业演示文稿。职场办公、教育学习、企业服务全覆盖,降本增效,释放创意!
- 99次使用
-
- Suno苏诺中文版
- 探索Suno苏诺中文版,一款颠覆传统音乐创作的AI平台。无需专业技能,轻松创作个性化音乐。智能词曲生成、风格迁移、海量音效,释放您的音乐灵感!
- 98次使用
查看更多
相关文章
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- 搞一个自娱自乐的博客(二) 架构搭建
- 2023-02-16 244浏览
-
- B-Tree、B+Tree以及B-link Tree
- 2023-01-19 235浏览
-
- mysql面试题
- 2023-01-17 157浏览
-
- MySQL数据表简单查询
- 2023-01-10 101浏览