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

如果查询的两个表大小相当,那么用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. PyQt4 在Windows下安装

    快来加入群[python爬虫交流群](群号570070796),发现精彩内容.     首先在网上下载sip文件下载完之后解压, 在Windows的开始菜单栏中进入sip的解压目录下:   在目录下面 ...

  2. win10+Anaconda3+CUDA9.0+CUDNN7.1+TensorFlow-gpu1.9+Pycharm

    想在win10上运行下YOLO的例子,要先配置环境,折腾了两天,终于好了,整理下自己觉得有用且正确的流程. win10+Anaconda3+CUDA9.0+CUDNN7.1+TensorFlow1.9 ...

  3. Fragment 使用详解

    极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...

  4. Oracle RAC 集群启动与停止

    Oracle RAC 启动时,需要使用 root 用户执行,为了方便,写了启动和停止的脚本, 将该脚本放到 /root/bin ,因为bin 目录本身就在环境变量里,所以使用时直接root用户运行脚本 ...

  5. Spring系列(一):Spring核心概念

    一.Spring概念 Spring是一种多层的J2EE应用程序框架,其核心就是管理资源组件以及依赖关系,Spring框架为现代基于java的企业应用程序提供了一个全面的编程和配置模型. 二.Sprin ...

  6. java并发编程(十六)----(线程池)java线程池的使用

    上节我们简单介绍了线程池,这次我们就来使用一下.Executors提供四种线程池,分别是:newCachedThreadPool,newFixedThreadPool ,newScheduledThr ...

  7. Eclipse高级操作 远程调试

    Eclipse高级操作 远程调试 JPDA是SUN JDK自带的远程调试机制.它提供了一套标准的调试接口,可以从虚拟机一级允许外界用特定协议探测虚拟机内部的运作细节.只要你装了JDK1.2以上的SUN ...

  8. 一文了解:Redis的AOF持久化

    Redis的AOF持久化 每当Redis-Server接收到写数据时,就把命令以文本形式追加到AOF文件里,当重启Redis服务时,AOF文件里的命令会被重新执行一次,重新恢复数据.当AOF过大时将重 ...

  9. 分享一个非常好用又好看的终端工具--Hyper (支持windows、MacOS、Linux)

    分享一个非常好用又好看的终端工具--Hyper 官网地址: https://hyper.is/ 打开官网,选择对应版本安装即可:(可能网络原因,无法下载, 可以从我分享的链接下载 链接: https: ...

  10. 为什么双重检查锁模式需要 volatile ?

    双重检查锁定(Double check locked)模式经常会出现在一些框架源码中,目的是为了延迟初始化变量.这个模式还可以用来创建单例.下面来看一个 Spring 中双重检查锁定的例子. 这个例子 ...