网上可以查到很多这样的说法:

如果查询的两个表大小相当,那么用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列的索引。

将下面的语句执行优化:

select count(uid) from user where uid in (SELECT did FROM demo);
select count(uid) from user where exists (SELECT 1 FROM demowhere demo.did = user.uid);

1.注意慢的原因就是内部每次与外部比较时,都需要遍历一次表操作,可以采用另外一个方法,在嵌套一层子查询,避免多次遍历操作

SELECT count(did) FROM demo where exists (SELECT uid FROM (SELECT uid from user) as b where b.uid = demo.did);

2.第二种优化就是先将子查询里的语句执行,使用GROUP_CONCAT将字段连接起来,

如果字符串长度不够可以使用:SET SESSION group_concat_max_len = 102400;

原sql:

SELECT
  c.id
 FROM
  c  此表有712995条数据
 LEFT JOIN u ON c.user_id = u.id
 LEFT JOIN doc ON c.doctor_id = doc.id
 LEFT JOIN s ON c.meal_id = s.id
 WHERE
  s.renew = 1
 AND c.orderstatus = 1
 AND c.endtime < UNIX_TIMESTAMP()
 AND c.org_type = 'c'
 AND u.is_doctor = 0
 AND u.active = 1
 AND doc.is_doctor IN (4, 5)
 AND doc.is_family_doctor = 1
 AND doc.active = 1
 AND c.user_id NOT IN (
  SELECT
   user_id
  FROM
   d  此表有934455条数据
  WHERE
   d.log LIKE '%结束'
 );

-- 执行时间为2.265s

优化后:

SET SESSION group_concat_max_len = 102400;

SELECT  GROUP_CONCAT(user_id)   FROM   d   WHERE  d.log LIKE '%结束';    -- 执行了0.521s

SELECT
  c.id
 FROM
  c
 LEFT JOIN u ON c.user_id = u.id
 LEFT JOIN doc ON c.doctor_id = doc.id
 LEFT JOIN s ON c.meal_id = s.id
 WHERE
  s.renew = 1
 AND c.orderstatus = 1
 AND c.endtime < UNIX_TIMESTAMP()
 AND c.org_type = 'c'
 AND u.is_d = 0
 AND u.active = 1
 AND doc.is_d IN (4, 5)
 AND doc.is_f_d = 1
 AND doc.active = 1
 AND c.user_id NOT IN (24986,24986,24986,24986,24986,24986,..............................................大概5千个id);

-- 执行时间1.579s

执行时间少了0.686s,但是GROUP_CONCAT(user_id)还执行了0.521s,所以总体时间没有什么差别(当前数量级),

而且后一个需要考虑字符串的大小问题。

目前就了解这些,以后有时间再细细琢磨。

MySQL IN和EXISTS的效率问题,以及执行优化的更多相关文章

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

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

  2. MySQL 子查询 EXISTS 和 NOT EXISTS

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

  3. mysql in与exists区别

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

  4. SQLSERVER语句 in和exists哪个效率高本人测试证明

    SQLSERVR语句 in和exists哪个效率高本人测试证明 最近很多人讨论in和exists哪个效率高,今天就自己测试一下 我使用的是客户的数据库GPOSDB(已经有数据) 环境:SQLSERVE ...

  5. 关于in与exists的效率讨论

    关于in与exists的效率讨论1).select * from A where id in (select id from B)以上查询使用了in语句,in只执行一次,他查出B表的所有id字段并缓存 ...

  6. Mysql 多表联合查询效率分析及优化

    1. 多表连接类型 1. 笛卡尔积(交叉连接) 在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用','  如: SELECT * FROM table1 CROSS JO ...

  7. in和exists的区别与SQL执行效率

    in和exists的区别与SQL执行效率最近很多论坛又开始讨论in和exists的区别与SQL执行效率的问题,本文特整理一些in和exists的区别与SQL执行效率分析 SQL中in可以分为三类: 1 ...

  8. in和exists哪个效率高本人测试证明

    in和exists哪个效率高本人测试证明 SQLSERVR语句 in和exists哪个效率高自己测试本人测试证明 最近很多人讨论in和exists哪个效率高,今天就自己测试一下 我使用的是客户的数据库 ...

  9. MySQL Execution Plan--NOT EXISTS子查询优化

    在很多业务场景中,会使用NOT EXISTS语句来确保返回数据不存在于特定集合,部分场景下NOT EXISTS语句性能较差,网上甚至存在谣言"NOT EXISTS无法走索引". 首 ...

随机推荐

  1. 林大妈的JavaScript基础知识(三):JavaScript编程(1)对象

    1. 对象的简单介绍与一些注意事项 JavaScript中具有几个简单数据类型:数字.字符串.布尔值.null值以及undefined值.除此之外其余所有值(包括数组.函数,甚至正则表达式)都是对象. ...

  2. 浅析java中的语法糖

    概述 编译器是一种计算机程序, 它主要的目的是将便于人编写.阅读.维护的高级计算机语言所写的源代码程序, 翻译为计算机能解读.运行的低阶机器语言的程序, 即可执行文件.而 javac 就是java语言 ...

  3. 爬虫获取搜狐汽车的配置信息 和swf动态图表的销量数据-------详细教学

    前情提要:需要爬取搜狐汽车的所有配置信息,具体配置对应的参数. 以及在动态图表上的历史销量. 比如: 一汽奥迪旗下Q5L 的<40 TFSI 荣享进取型 国VI >的历史销量和该配置的参数 ...

  4. idea 新建不了servlet文件 方法(1)

    在pem.xml中添加较新版本的servletapi包 <dependency> <groupId>javax.servlet</groupId> <arti ...

  5. Ubuntu 18.04 LTS版本 GoldenDict安装与配置

    为何安装? GoldenDict是一款Linux下很好用的词典软件,其具有的关于词典的裁剪功能使得用户能够方便地对各种词典进行添加或删除,其具有的屏幕取词功能能够帮助用户方便地进行翻译,其具有的网络源 ...

  6. fatal: remote origin already exists.解决方法

    git remote add origin1 http://github.com/xxx/xxx.git origin名字冲突,换一个名字 遇到这种问题时表示已经有一个origin,冲突了,可能原因是 ...

  7. Python 学习笔记(6)— 字符串格式化

    字符串格式化处理 远古写法 以前通常使用运算符号 % ,%s 插入的值 String 类型,%.3f 指插入的值为包含 3 位小数的浮点数: format1 = "%s, %s!" ...

  8. C# 发送邮件 并自定义邮件格式

    话不多说,直接上代码 //邮件提醒 string Body = @"Dear " + list.Rows[i]["people"] + ":<b ...

  9. bat 下 字符串拆分 类似 split 可以使用 for /f delims

    @echo offset strin=AA,BB,CC,DDfor /f "tokens=1,2,3,4 delims=, " %%a in ('echo %strin%') do ...

  10. centos7通过yum安装docker

    ##yum源安装#1.更新yumyum update #2.删除旧版本yum remove docker \docker-client \docker-client-latest \docker-co ...