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

如果查询的两个表大小相当,那么用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. js异步解决方法

    在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作.在服务器端,"异步模式"甚至是唯一的模式,因为执行环境是单线程的,如果允许同步执行所有ht ...

  2. CentOS7源码安装Nginx

    系统平台:腾讯云服务器 CentOS 7.3 64位 一.安装编译工具及库文件 [root@VM_0_5_centos ~]# yum install -y make zlib zlib-devel ...

  3. .net RabbitMQ 介绍、安装、运行

    RabbitMQ介绍 什么是MQ Message Queue(简称:MQ),消息队列 顾名思义将内容存入到队列中,存入取出的原则是先进先出.后进后出. 其主要用途:不同进程Process/线程Thre ...

  4. Rust写时复制Cow<T>

    写时复制(Copy on Write)技术是一种程序中的优化策略,多应用于读多写少的场景.主要思想是创建对象的时候不立即进行复制,而是先引用(借用)原有对象进行大量的读操作,只有进行到少量的写操作的时 ...

  5. 关于python中的特殊方法

    研究了几个小时,大概对python中的特殊方法一知半解,现在写写自己的理解,以及记录一些找到的资源.待自己有比较深入理解的时候,再来更新 https://docs.python.org/3/refer ...

  6. host配置

    host添加地址 今天是我第一天入职,坐到工位的第一件事就是配置host,因为连接测试环境需要本地授权,所以要配置.这里简单记录下配置中遇到的问题和操作的步骤 操作环境是win10,之前公司一直使用的 ...

  7. Linux基础进程管理优先级

    一.进程优先级 Linux进程调度及多任务 每个cpu(或者cpu核心)在一个时间点上只能处理一个进程,通过时间片技术,Linux实际能够运行的进程(和线程数)可以超出实际可用的cpu及核心数量.Li ...

  8. 3、大型项目的接口自动化实践记录----开放API练习

    开始做实际项目前,先拿个网上的简单API练下手 一.API说明: 接口信息 接口名:京东获取单个商品价格 地址:http://p.3.cn/prices/mgets 入参:skuids=J_商品ID& ...

  9. Adapter适配器模式--图解设计模式

    第二章: Adapter 模式 Adapter模式分为两种: 1.类适配器模式 2.委托适配器 我看的是<图解设计模式>这本书,这小鬼子说的话真难懂,只能好好看代码理解. 先说适配器模式要 ...

  10. LR(1)语法分析器生成器(生成Action表和Goto表)java实现(一)

    序言 : 在看过<自己实现编译器链接器>源码之后,最近在看<编译器设计>,但感觉伪代码还是有点太浮空.没有掌握的感觉,也因为内网几乎没有LR(1)语法分析器生成器的内容,于是我 ...