当前位置: 首页 > news >正文

mysql -- exists 替换 in

exists对外表用loop逐条查询,每次查询都会查看exists的条件语句,当 exists里的条件语句能够返回记录行时(无论记录行是的多少,只要能返回),条件就为真,返回当前loop到的这条记录,反之如果exists里的条 件语句不能返回记录行,则当前loop到的这条记录被丢弃,exists的条件就像一个boolean条件,当能返回结果集则为true,不能返回结果集则为 false

如下:

select * from user where exists (select 1);

对user表的记录逐条取出,由于子条件中的select 1永远能返回记录行,那么user表的所有记录都将被加入结果集,所以与 select * from user;是一样的

又如下

select * from user where exists (select * from user where userId = 0);

可以知道对user表进行loop时,检查条件语句(select * from user where userId = 0),由于userId永远不为0,所以条件语句永远返回空集,条件永远为false,那么user表的所有记录都将被丢弃

not exists与exists相反,也就是当exists条件有结果集返回时,loop到的记录将被丢弃,否则将loop到的记录加入结果集

总的来说,如果A表有n条记录,那么exists查询就是将这n条记录逐条取出,然后判断n遍exists条件 

 

 

in查询相当于多个or条件的叠加,这个比较好理解,比如下面的查询

select * from user where userId in (1, 2, 3);

等效于

select * from user where userId = 1 or userId = 2 or userId = 3;

not in与in相反,如下

select * from user where userId not in (1, 2, 3);

等效于

select * from user where userId != 1 and userId != 2 and userId != 3;

总的来说,in查询就是先将子查询条件的记录全都查出来,假设结果集为B,共有m条记录,然后在将子查询条件的结果集分解成m个,再进行m次查询

 

值得一提的是,in查询的子条件返回结果必须只有一个字段,例如

select * from user where userId in (select id from B);

而不能是

select * from user where userId in (select id, age from B);

而exists就没有这个限制

 

下面来考虑exists和in的性能

考虑如下SQL语句

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

2: select * from A where A.id in (select id from B);

 

查询1.可以转化以下伪代码,便于理解

for ($i = 0; $i < count(A); $i++) {

  $a = get_record(A, $i); #从A表逐条获取记录

  if (B.id = $a[id]) #如果子条件成立

    $result[] = $a;

}

return $result;

大概就是这么个意思,其实可以看到,查询1主要是用到了B表的索引,A表如何对查询的效率影响应该不大

 

假设B表的所有id为1,2,3,查询2可以转换为

select * from A where A.id = 1 or A.id = 2 or A.id = 3;

这个好理解了,这里主要是用到了A的索引,B表如何对查询影响不大

 

下面再看not exists 和 not in

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

2. select * from A where A.id not in (select id from B);

看查询1,还是和上面一样,用了B的索引

而对于查询2,可以转化成如下语句

select * from A where A.id != 1 and A.id != 2 and A.id != 3;

可以知道not in是个范围查询,这种!=的范围查询无法使用任何索引,等于说A表的每条记录,都要在B表里遍历一次,查看B表里是否存在这条记录

故not exists比not in效率高

 

mysql中的in语句是把外表和内表作hash 连接,而exists语句是对外表作loop循环,每次loop循环再对内表进行查询。一直大家都认为exists比in语句的效率要高,这种说法其实是不准确的。这个是要区分环境的。
 

如果查询的两个表大小相当,那么用in和exists差别不大。 
如果两个表中一个较小,一个是大表,则子查询表大的用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要快。 
in 与 =的区别 
select name from student where name in ('zhang','wang','li','zhao'); 
与 
select name from student where name='zhang' or name='li' or name='wang' or name='zhao' 
的结果是相同的。

转载于:https://www.cnblogs.com/daijiabao/p/11283532.html

相关文章:

  • unreal——导入模型时是否创建material呢?一切随你
  • 2019/8/1 LCA(最近公共祖先) (2)
  • Time.realtimeSinceStartup——秒秒秒单位
  • 成都边锋 云端虚拟化工具 系统驱动层 原理初窥
  • SpringBoot入门最详细教程
  • unreal——控制器
  • flex与js交互浅析
  • python安装pip以及使用pip安装requests等模块
  • 使用luac加密lua文件
  • mac安装android studio+NDK
  • matrix(DP杂题,思维题)
  • xlua的加固
  • 架构模式: 无服务器部署
  • persistence配置
  • xlua崩溃
  • 时间复杂度分析经典问题——最大子序列和
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • hadoop集群管理系统搭建规划说明
  • Iterator 和 for...of 循环
  • JavaScript的使用你知道几种?(上)
  • node.js
  • Python学习之路13-记分
  • Quartz初级教程
  • vue:响应原理
  • vue-loader 源码解析系列之 selector
  • 翻译:Hystrix - How To Use
  • 浮动相关
  • 给第三方使用接口的 URL 签名实现
  • 关于List、List?、ListObject的区别
  • 如何设计一个比特币钱包服务
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 事件委托的小应用
  • 无服务器化是企业 IT 架构的未来吗?
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ​ubuntu下安装kvm虚拟机
  • (12)Linux 常见的三种进程状态
  • (Oracle)SQL优化技巧(一):分页查询
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (一)基于IDEA的JAVA基础1
  • (转)VC++中ondraw在什么时候调用的
  • (转)菜鸟学数据库(三)——存储过程
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .bat批处理出现中文乱码的情况
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .htaccess配置常用技巧
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET Framework杂记
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • /proc/vmstat 详解
  • ::前边啥也没有