大神级回答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是世界第一语言!”平时不苟言笑,埋头苦干的 ...
随机推荐
- RouterOS基础安装配置
安装 光盘安装 载入光盘,按"A"全选按"I"进行安装,然后提示不否用旧的配置,按"N"全新安装,警告时按"Y"确定 安 ...
- [洛谷P4436] HNOI/AHOI2018 游戏
问题描述 一次小G和小H在玩寻宝游戏,有n个房间排成一列,编号为1,2,...,n,相邻的房间之间都有一道门.其中一部分门上锁(因此需要有对应的钥匙才能开门),其余的门都能直接打开.现在小G告诉了小H ...
- LeetCode--072--编辑距离(python)
给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 . 你可以对一个单词进行如下三种操作: 插入一个字符删除一个字符替换一个字符示例 1: 输入: ...
- HTTP content-type及POST提交数据方式
Content-Type(内容类型),一般指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式.什么编码读取这个文件,这也是一些网页点击的结果却是一个文件 ...
- linux运维、架构之路-rpm定制、本地yum仓库搭建
一.定制rpm包 1.环境 [root@m01 ~]# cat /etc/redhat-release CentOS release 6.9 (Final) [root@m01 ~]# uname - ...
- jquery attr()方法获取input的checked属性问题
问题:经常使用jQuery插件的attr方法获取checked属性值,获取的值的大小为未定义,此时可以用prop方法获取其真实值,下面介绍这两种方法的区别: 1.通过prop方法获取checked属性 ...
- SpringBoot项目的前端+thymeleaf模板引擎
SpringBoot项目创建之后,后台的框架是SpringMVC.但前端的resource和template目录都是空的.这个时候需要创建前台页面. 习惯上,我们会创建JSP,但是,SpringBoo ...
- vue路由实例
router.js: import Vue from 'vue' import Router from 'vue-router' import Home from '@/components/Home ...
- ijkplayer阅读学习笔记之从代码上看播放流程
http://blog.csdn.net/i_do_can/article/details/51374732
- C++模板声明与实现分开--由此想到的编译,链接原理
参考了以下两篇文章: C++编译链接原理简介 语言程序编译过程 2 问题来源:当模板文件的实现与声明分开在不同文件中时,链接时会提示找不到相应模板函数,如下 一,编译和链接的大概原理: 1,编译,遍 ...