大神级回答exists与in的区别
google搜了一下,很多帖子,而且出发点不同,各有各的道理,但是有一个帖子讲的特别好:
http://zhidao.baidu.com/question/134174568.html
忍不住在百度上回复了一下,怒赞,没想到别人早就回复过了:围观大神级回答。确实名副其实!
================in和exists=============================
in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。
如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:
例如:表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要快。
------------------------我的评论-----------------------------------------
1本质上是要利用索引,2要区分大表小表,3not exists子查询能使用索引,速度更快。我的真实SQL是这样的:
INSERT INTO journal_curr 
SELECT '2008-10-01' AS date_imp, act_numero, act_sexe, titre, act_nom, act_nom_abrege, act_sous_titre,act_adr_numero,act_adr_rue,
ltrim(concat( IFNULL(act_adr_numero,''),' ',act_adr_rue)) AS act_adr,act_adr_complement,act_cp,LEFT(act_cp,2) AS region,act_ville,act_pays, nb_exempl 
FROM journal_abonn  INNER JOIN actif 
ON (journal_abonn.ref_client = actif.act_numero) 
   AND (ref_journal='NOUVEURO')
   AND (act_pays<>'ALLEMAGNE')
   AND (  ((date_abonn<='2008-10-01') AND (date_fin_abonn>='2008-10-01') AND (date_abonn_fin_envoi IS NULL))
       OR ((date_abonn<='2008-10-01') AND (date_abonn_fin_envoi>='2008-10-01'))
       OR ((act_type_abonne=4) AND ((date_fin_abonn>='2008-10-01') AND (date_abonn_fin_envoi IS NULL)))
       OR ((act_type_abonne=4) AND (date_fin_abonn IS NULL) AND (date_abonn_fin_envoi IS NULL))
       OR ((act_type_abonne=4) AND ((date_abonn_fin_envoi>='2008-10-01')))
       )
   AND (ref_abonn_new NOT IN (SELECT ref_abonn_new FROM journal_suspension  
                                                   WHERE (debut_suspension<='2008-10-01')
                                                     AND (fin_suspension>='2008-10-01')
                                                     AND (ref_journal='NOUVEURO')
                             )
       )
自从给journal_abonn加了ref_client加了索引以后,时间从30分钟下降到几秒(注意,我没给ref_abonn_new加索引)。
有趣的是,我这个例子刚好journal_abonn是大表,journal_suspension是小表,符合IN的使用条件。
大表真正使用的关键索引是ref_client,而不是ref_abonn_new,所以可以充分利用上。
小表计算速度无所谓,而且根据研究小表应该也是一次计算完后放在内存中。
另外,我这里是NOT IN,但是速度仍然很快,说明仍然利用上了索引,难道大神级回复也有小错?
================================================================
另外,我重新整理一下所有我搜到的发言,都很有道理:
通过使用exist,oracle系统会首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间(我的评论,主表小当然应该先过滤主查询)。oracle系统在执行in子查询时,首先执行子查询(我的评论,从表小当然应该先过滤子查询),并将获得的结果列表存放在在一个加了索引的临时表中。在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。这也就是使用exists比使用in通常查询速度快的原因。
下面是一个非关联子查询: 
  select staff_name from staff_member where staff_id 
  in (select staff_id from staff_func); 
  而下面是一个关联子查询: 
  select staff_name from staff_member where staff_id in (select staff_id from staff_func where staff_member.staff_id=staff_func.staff_id); 
  以上返回的结果集是相同的,可是它们的执行开销是不同的: 
  非关联查询的开销——非关联查询时子查询只会执行一次,而且结果是排序好的,并保存在一个ORACLE的临时段中,其中的每一个记录在返回时都会被父查询所引用。在子查询返回大量的记录的情况下,将这些结果集排序,以及将临时数据段进行排序会增加大量的系统开销。 
  关联查询的开销——对返回到父查询的的记录来说,子查询会每行执行一次。因此,我们必须保证任何可能的时候子查询用到索引。 
楼上说法片面,in和exist,各有快的时候,主要是看你的筛选条件是在主查询上还是在子查询上。
下面是oracle文档,:)
In certain circumstances, it is better to use IN rather than EXISTS. In general, if the selective predicate is in the subquery, then use IN. If the selective predicate is in the parent query, then use EXISTS.
Sometimes, Oracle can rewrite a subquery when used with an IN clause to take advantage of selectivity specified in the subquery. This is most beneficial when the most selective filter appears in the subquery and there are indexes on the join columns. Conversely, using EXISTS is beneficial when the most selective filter is in the parent query. This allows the selective predicates in the parent query to be applied before filtering the rows against the EXISTS criteria.
exists不需要记录,当存在的时候就返回。
用exists只检查行的存在性,而in检查到行里的实际的值。
参考:
http://bbs.csdn.net/topics/190124638
http://blog.csdn.net/lick4050312/article/details/4476333
A,B两个表
    当只显示一个表的数据如A,关系条件只一个如ID时,使用IN更快:select * from A where id in (select id from B)
    当只显示一个表的数据如A,关系条件不只一个如ID,col1时,使用IN就不方便了,可以使用EXISTS:select * from A where exists (select 1 from B where id = A.id and col1 = A.col1)
    当只显示两个表的数据时,使用IN,EXISTS都不合适,要使用连接:select * from A left join B on id = A.id
参考:
http://www.cnblogs.com/AllUserBegin/p/3513084.html
大神级回答exists与in的区别的更多相关文章
- 为什么学习python?(知乎大神的回答)
		
学习PHP 是因为得到一份工作 学习Java 是因为他们选修了计算机科学这门课程 学习python 是因为爱这门语言,因为寻求美
 - 知乎大神对IAAS,SAAS,PAAS区别的理解
		
你一定听说过云计算中的三个“高大上”的你一定听说过云计算中的三个“高大上”的概念:IaaS.PaaS和SaaS,这几个术语并不好理解.不过,如果你是个吃货,还喜欢披萨,这个问题就好解决了!好吧,其实你 ...
 - 为何你跟着滴滴D8级前端大神撸代码,技术却依旧原地踏步?
		
引子 听说最近有很多小伙伴,热衷于在慕课网上学习各种前端实战教程,并以完成项目为奋斗目标.比如本文接下来要提到的<Vue2.0高级实战之开发移动端音乐App>,这门课程的传授者是来自滴滴D ...
 - 对话机器学习大神Yoshua Bengio(上)
		
Yoshua Bengio教授(个人主页)是机器学习大神之一,尤其是在深度学习这个领域.他连同Geoff Hinton老先生以及 Yann LeCun(燕乐存)教授,缔造了2006年开始的深度学习复兴 ...
 - 对话机器学习大神Yoshua Bengio(下)
		
对话机器学习大神Yoshua Bengio(下) Yoshua Bengio教授(个人主页)是机器学习大神之一,尤其是在深度学习这个领域.他连同Geoff Hinton老先生以及 Yann LeCun ...
 - zz独家专访AI大神贾扬清:我为什么选择加入阿里巴巴?
		
独家专访AI大神贾扬清:我为什么选择加入阿里巴巴? Natalie.Cai 拥有的都是侥幸,失去的都是人生 关注她 5 人赞同了该文章 本文由 「AI前线」原创,原文链接:独家专访AI大神贾扬清:我 ...
 - 【web前端面试题整理04】阿里一行之大神面对面
		
前言 这段时间我在河南一家公司当了一段时间的前端主管,最后可耻的匿了,原因各种各样,最主要的就是不想呆在郑州了. 其实这里的同事还是很不错的,面对老总最后的挽留我不是没有动心,而是这个地方确实不太好, ...
 - ScrollView嵌套ListView的滑动冲突问题,是看大神的方法的,作为学习以后用的到
		
在工作中,曾多次碰到ScrollView嵌套ListView的问题,网上的解决方法有很多种,但是杂而不全.我试过很多种方法,它们各有利弊. 在这里我将会从使用ScrollView嵌套ListView结 ...
 - Github欢乐多 PHP神级代码引发吐槽热
		
前日,github的PHP板块惊现一段能够提升70%运行效率的代码,引发了全世界众多网友的吐槽和调侃,“awesome!”.“well done!”.“PHP是世界第一语言!”平时不苟言笑,埋头苦干的 ...
 
随机推荐
- 8:Spring Boot Shiro记住密码
			
1,添加Cookie 2,添加安全管理器中 3,配置记住我, 4 ,在登录页面中加我rememberMe复选框 /** * 1.配置Cookie对象 * 记住我的cookie:rememberMe * ...
 - [ZJU 1004] Anagrams by Stack
			
ZOJ Problem Set - 1004 Anagrams by Stack Time Limit: 2 Seconds Memory Limit: 65536 KB How can a ...
 - Leetcode 4. Median of Two Sorted Arrays(中位数+二分答案+递归)
			
4. Median of Two Sorted Arrays Hard There are two sorted arrays nums1 and nums2 of size m and n resp ...
 - 【BZOJ2200】道路和航线(并查集,拓扑排序,最短路)
			
题意:n个点,有m1条双向边,m2条单向边,双向边边长非负,单向边可能为负 保证如果有一条从x到y的单项边,则不可能存在从y到x的路径 问从S出发到其他所有点的最短路 n<=25000,n1,m ...
 - 01-pandas基础-Series与DataFrame
			
一.Series: 1,介绍:Series是以中类似于一维数组的对象,由一维数组以及与之相关的标签组成 特点:索引在左边,值在右边.在创建时,若我们未给数据指定索引,Series会自动创建一个0到N- ...
 - java读取ldif文件并创建新的节点
			
所需jar包ldap.jar. jldap-4.3-source.jar http://www.java2s.com/Code/Jar/l/Downloadldapjar.htm 浏览器输入http: ...
 - es之java搜索文档
			
1:搜索文档数据(单个索引) @Test public void getSingleDocument(){ GetResponse response = client.prepareGet(" ...
 - Linux驱动开发4——并发和竞态
			
Linux系统处于一个高并发的运行环境,不管是系统调用还是中断都要求可重入,但是有一些系统资源处于临界区,因此,必须保证临界区资源访问的原子性. 对于临界区资源被占用时,发起访问的进程,有三种处理方法 ...
 - Python编程:从入门到实践—变量和简单数据类型
			
变量的命名和使用 #!/usr/bin/env python# -*- encoding:utf-8 -*- message ="Hello Python world!"print ...
 - c# Task waitAll,WhenAll
			
wait 阻塞的 when是异步的非阻塞的. Task[] tlist = new Task[] { Task.Run(() => { Thread.Sleep(3000); }), Task. ...