in 和exists

对于以上两种查询条件,in是把外表和内表作hash 连接,而exists 是对外表作loop 循环,每次loop 循环再对内表进行查询。

一直以来认为exists 比in 效率高的说法是不准确的。在不同的情况下,exists与in的性能各有优缺项,如果查询的两个表大小相当,那么用in 和exists 差别不大。

下面以实例来进行说明:

select *  from A where id in(select id from B);

select *  from A where exists (select 1 from B where A.id = B.id);

1、in的应用原理

在select *  from A where id in(select id from B); 中,in()中的子查询只执行一次,它查询出B表中的所有ID值并缓存起来;之后,在内存中检查A表的id是否与B表中的id值相等,如果相等则则将A表的记录加入到结果集中,直到遍历完A表中的所有记录。

它查询的过程类似于一下过程

Array A={select * from A};
Array B={select id from B};
for (int i=0;i<A.length;i++){
for (int j=0;j<B.length;j++){
if (A[i].id == B[j].id){
resultSet.add(A[i]);
break;
}
}
}

如:A表有10000条记录,B表有1000000条记录,那么使用in最多可能有10000*1000000次遍历,效率很差;

A表有10000条记录,B表有100条记录,那么使用in最多可能有10000*100次遍历,遍历次数大大减少,效率大大提升;

结论:in()适合B表比A表数据小的情况

2、exists的应用原理

在select * from A where exists (select 1 from B where A.id=B.id);之中
exists()会执行A.length次,它并不缓存exists()结果集,因为exists()结果集的内容并不重要,重要的是其内查询语句的结果集空或者非空,空则返回false,非空则返回true。
它的查询过程类似于以下过程:

Array A=(select * from A);
for(int i=0;i<A.length;i++) {
if(exists(A[i].id) { //执行select 1 from B where B.id=A.id是否有记录返回
resultSet.add(A[i]);
}
}
return resultSet;

当B表比A表数据大时适合使用exists(),因为它没有那么多遍历操作,只需要再执行一次查询就行。
如:A表有10000条记录,B表有1000000条记录,那么exists()会执行10000次去判断A表中的id是否与B表中的id相等。
如:A表有10000条记录,B表有100000000条记录,那么exists()还是执行10000次,因为它只执行A.length次,可见B表数据越多,越适合exists()发挥效果。
再如:A表有10000条记录,B表有100条记录,那么exists()还是执行10000次,还不如使用in()遍历10000*100次,因为in()是在内存里遍历比较,而exists()需要查询数据库,我们都知道查询数据库所消耗的性能更高,而内存比较很快

结论:exists()适合B表比A表数据大的情况

当A表数据与B表数据一样大时,in与exists效率差不多,可任选一个使用。

数据从一个表往另外一个表中插入数据时使用EXISTS:

在插入记录前,需要检查这条记录是否已经存在,只有当记录不存在时才执行插入操作,可以通过使用 EXISTS 条件句防止插入重复记录。
insert into A (name,age) select name,age from B where not exists (select 1 from A where A.id=B.id);

EXISTS与IN的使用效率的问题,通常情况下采用exists要比in效率高,因为IN不走索引。但要看实际情况具体使用:IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

关于EXISTS:
EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值TRUE 或FLASE 。
EXISTS指定一个子查询,检测行的存在。
语法:EXISTS subquery
参数:subquery 是一个受限的 SELECT 语句 (不允许有 COMPUTE 子句和 INTO 关键字)。
结果类型:Boolean 如果子查询包含行,则返回 TRUE ,否则返回 FLASE 。
结论:select * from A where exists (select 1 from B where A.id=B.id) 
EXISTS(包括 NOT EXISTS )子句的返回值是一个boolean值。 EXISTS内部有一个子查询语句(SELECT ... FROM...), 我将其称为EXIST的内查询语句。其内查询语句返回一个结果集。 EXISTS子句根据其内查询语句的结果集空或者非空,返回一个布尔值。
一种通俗的可以理解为:将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果取非空值,则EXISTS子句返回TRUE,这一行行可作为外查询的结果行,否则不能作为结果。
分析器会先看语句的第一个词,当它发现第一个词是SELECT关键字的时候,它会跳到FROM关键字,然后通过FROM关键字找到表名并把表装入内存。接着是找WHERE关键字,如果找不到则返回到SELECT找字段解析,如果找到WHERE,则分析其中的条件,完成后再回到SELECT分析字段。最后形成一张我们要的虚表。
WHERE关键字后面的是条件表达式。条件表达式计算完成后,会有一个返回值,即非0或0,非0即为真(true),0即为假(false)。同理WHERE后面的条件也有一个返回值,真或假,来确定接下来执不执行SELECT。

Sql中EXISTS与IN的使用及效率的更多相关文章

  1. SQL中EXISTS怎么用[转]

    SQL中EXISTS怎么用 1 2 3 4 分步阅读 EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False 方法/步骤 1 EXISTS用于 ...

  2. SQL中EXISTS和IN用法

    SQL中EXISTS的用法  指定一个子查询,检测行的存在. 语法:EXISTS subquery 参数:subquery 是一个受限的 SELECT 语句 (不允许有 COMPUTE 子句和 INT ...

  3. sql中exists和not exists的用法

    该文转载自:http://www.cnblogs.com/mytechblog/articles/2105785.html sql中exists,not exists的用法 exists : 强调的是 ...

  4. 十、SQL中EXISTS的用法 十三、sql server not exists

    十.SQL中EXISTS的用法 EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False EXISTS 指定一个子查询,检测 行 的存在. 语法 ...

  5. sql 中 exists用法

    SQL中EXISTS的用法   比如在Northwind数据库中有一个查询为SELECT c.CustomerId,CompanyName FROM Customers cWHERE EXISTS(S ...

  6. 数据库——SQL中EXISTS怎么用2(转)

    数据库sql语句的exists总结 sql exists in 学习 先来比较下语法: --deals=交易表,areas=地域表,例如香港:我们的目的:查看有交易的地域 select * from ...

  7. sql中exists和notexists用法总结(并和in的比较)

    首先头脑中有三点概念: 1.EXISTS子查询找到的提交 NOT EXISTS 子查询中 找不到的提交 说明:不要去翻译为存在和不存在,把脑袋搞晕. 2.建立程序循环的概念,这是一个动态的查询过程.如 ...

  8. SQL中EXISTS的使用

    1.简介 不相关子查询:子查询的查询条件不依赖于父查询的称为不相关子查询. 相关子查询:子查询的查询条件依赖于外层父查询的某个属性值的称为相关子查询,带EXISTS 的子查询就是相关子查询 EXIST ...

  9. SQL中exists、not exists以及in、not in的区别和使用

    exists : 强调的是是否返回结果集,不要求知道返回什么, 比如:   select name from student where sex = 'm' and mark exists(selec ...

随机推荐

  1. linux tomcat启动后无法访问

    先是按网上资料先下载安装包,然后上传到linux,启动后发现8080端口并未被占用.查了很多资料,不知道神马原因了.最后用yum安装后就可以访问了. 教程如下: 本教程介绍在CentOS 7服务器上使 ...

  2. 微信小程序内容组件图标 icon

    小程序内置了一下图标可以用 需要自定义图标的看这里 ==>微信小程序中使用iconfont/font-awesome等自定义字体图标 小程序内置图标使用示例 <icon type=&quo ...

  3. js原生轮播

    js原生轮播 今天用js做了轮播图,做的不怎么好,希望大家能够看懂. 效果: 1.鼠标放在轮播图上自动停止 2.鼠标离开轮播图自动播放 3.鼠标点击轮播图上的小圆点跳转到相应的图上. 代码: < ...

  4. 运行vbs脚本

    VBS是基于Visual Basic的脚本语言. VBS的全称是:Microsoft Visual Basic Script Edition.(微软公司可视化BASIC脚本版). 其语言类似Visua ...

  5. Python——列表深浅拷贝

    一.深浅拷贝 如果希望将列表复制一份,通过列表的内置方法copy就可以实现: s = [[1,2],3,4] s1 = s.copy() print(s) print(s1) 拷贝出的列表s1与原列表 ...

  6. 25.纯 CSS 创作一个慧星拖尾效果的 loader 动画

    原文地址:https://segmentfault.com/a/1190000014916281 简化地址:https://codepen.io/pen/?editors=1100 HTML代码: & ...

  7. Chrome(谷歌浏览器)和Firefox浏览器flash的swf文件发黑不透明问题解决方法

    一直以来看到各大网站的FLASH都是黑框框的,很好奇,难道他们不知道flash是可以设成透明的?于是用IE Tab插件浏览了下,发现人家的网页又正常,这样一来我就开始怀疑是我的Chrome有问题,于是 ...

  8. JS 函数(arguments、箭头函数、bind)

    参数 函数内部可用的 arguments 对象来访问函数的实参 注意 在函数递归调用的时候(在某一刻同一个函数运行了多次,也就是有多套实参),那么 arguments 属性的值是最近一次该函数调用时传 ...

  9. Linux下安装FTP服务(Ubuntu)

    在Ubuntu 14.04 上安装 FTP 服务 第一步>>更新库 linuxidc@linuxidc:~$ sudo apt-get update 第二步>>采用如下命令安装 ...

  10. react-native Animated, 旋转动画

    Animated 仅封装了四个可以动画化的组件: View.Text.Image.ScrollView 可以使用 Animated.createAnimatedComponent()来封装你自己的组件 ...