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

的结果是相同的。

mysql in和exists性能比较和使用【转】的更多相关文章

  1. mysql in和exists性能比较和使用

    in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询.一直以来认为exists比in效率高的说法是不准确的. 如果查询的两个表大小相当,那么用i ...

  2. SQL Server-聚焦LEFT JOIN...IS NULL AND NOT EXISTS性能分析(十七)

    前言 本节我们来分析LEFT JOIN和NOT EXISTS,简短的内容,深入的理解,Always to review the basics. LEFT JOIN...IS NULL和NOT EXIS ...

  3. MySQL 子查询 EXISTS 和 NOT EXISTS(转)

    MySQL EXISTS 和 NOT EXISTS 子查询 MySQL EXISTS 和 NOT EXISTS 子查询语法如下: SELECT ... FROM table WHERE EXISTS ...

  4. MYSQL使用PMM进行性能监控

    简介Percona监视和管理(PMM)是一个用于管理和监视MySQL和MongoDB性能的开源平台.它是由Percona与托管数据库服务.支持和咨询领域的专家合作开发的. PMM是一个免费的开源解决方 ...

  5. (转)一个MySQL 5.7 分区表性能下降的案例分析

    一个MySQL 5.7 分区表性能下降的案例分析 原文:http://www.talkwithtrend.com/Article/216803 前言 希望通过本文,使MySQL5.7.18的使用者知晓 ...

  6. MySQL 8.0复制性能的提升(翻译)

    What’s New With MySQL Replication in MySQL 8.0 MySQL复制从问世到现在已经经历了多个年头,它的稳定性和可靠性也在稳步的提高.这是一个不停进化的过程,由 ...

  7. mysql中影响数据库性能的因素讲解

    mysql中影响数据库性能的因素讲解 在本篇文章中我们给大家讲述了mysql中影响性能的因素以及相关知识点内容,有兴趣的朋友参考下 关于数据库性能的故事 面试时多多少少会讲到数据库上的事情,“你对数据 ...

  8. mysql in与exists区别

    1.exists是对外表做loop循环,每次loop循环再对内表(子查询)进行查询,那么因为对内表的查询使用的索引(内表效率高,故可用大表),而外表有多大都需要遍历,不可避免(尽量用小表),故内表大的 ...

  9. MySQL字符集不一致导致性能下降25%,你敢信?

    故事是这样的: 我在对MySQL进行性能测试时,发现CPU使用率接近100%,其中80%us, 16%sys,3%wa,iostat发现磁盘iops2000以下,avgqu-sz不超过3,%util最 ...

随机推荐

  1. <Android 基础(十七)> ViewPager介绍

    介绍 Layout manager that allows the user to flip left and right through pages of data. You supply an i ...

  2. 客户端使用自定义代理类访问WCF服务

    通常在客户端访问WCF服务时,都需要添加服务引用,然后在客户端app.config或web.config文件中产生WCF服务的客户端配置信息.若是每添加一个服务都是这样做,这样势必会将比较麻烦,能否简 ...

  3. SharePoint 2010 究竟需要占用多少服务器资源?

    SharePoint 安装目录(即SharePoint Root)大约 300M 磁盘空间. SharePoint Config 数据库,60M. Admin Center 数据库,100M. 默认安 ...

  4. 【原创】SQL SERVER 2012安装配置说明(多图详解)

    1. 优先安装软件 1. net framework3.5. 2. 在安装SQL SERVER 2012前需要3.5的支持.在WIN 2012系统可以在系统管理的添加角色和功能中安装,如下将[.NET ...

  5. Python动态类型简单介绍

    动态类型以及它提供的多态性,无疑是Python语言简洁性和灵活性的基础.   一.变量 <1>变量创建 一个变量a.当代码第一次给它赋值时就创建了它,之后的赋值将会改变已创建的变量名的值. ...

  6. 使用正则表达式验证IP地址

    实现效果: 知识运用: 实现代码: public bool validate(string str_IP) { string regex = @"(25[0-5]|2[0-4]\d|[0-1 ...

  7. python3中使用HTMLTestRunner.py报ImportError: No module named 'StringIO'的解决办法

    .原因是官网的是python2语法写的,看官手动把官网的HTMLTestRunner.py改成python3的语法: 参考:http://bbs.chinaunix.net/thread-415474 ...

  8. redis 系列 在 vs上 set,get 键值

    1.启动两个 cmd,一个用于打开服务,一个用于运行客户端. 详细步骤可见上一篇文章 2.下载nuget的 ServiceStack.Redis;  ,并在using中引用 ,详细步骤可见上一篇文章 ...

  9. Spring boot 自动配置自定义配置文件

    示例如下: 1.   新建 Maven 项目 properties 2.   pom.xml <project xmlns="http://maven.apache.org/POM/4 ...

  10. matlab 大块注释和取消注释的快捷键

    matlab 大块注释和取消注释的快捷键 注释:Ctrl+R 取消注释:Ctrl +T