1. IN在MySQL中是先查询子查询的表,然后将内表与外表进行一个笛卡尔积,再按条件进行筛选,在内表数据相对较小时,IN的速度较快

2.用IN效率低的原因

  • 跟实际的关联数据类型
  • 列的索引
  • 表数据大小
  • 等等情况

3.使用EXISTS来替代IN

  • EXISTS是先将外表作为驱动表,每次都是去查询外表数据,然后再进行判断,如果成立就将结果保留,否则则删除该行
  • 与IN的区别就在于:如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in, 反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。
  • 驱动顺序的不同:IN先执行子查询,EXISTS以外层为驱动表,先被访问
  • 逻辑:IN是以外表和内表进行连接,EXISTS是对外表的循环
  • 使用 not in 和 not exists
  • not in会造成子查询的全表扫描,没使用到索引,而not exists的子查询仍然能用上索引,理论上无论内表大还是外表大,not exists都会效率更高,但实际上不一定
  • 案例:
--users表有1000条记录,id自增,id都大于0

select * from users where exists (select * from users limit 0); --输出多少条记录?
select * from users where exists (select * from users where id < 0); --输出多少条记录?

答案(请选中查看):
10000条
0条
原因:exists查询的本质,只要碰到有记录,则返回true;所以limit根本就不会去管,或者说执行不到
exists可以完全代替in吗?
不能。

例如:
-没有关联字段的情况:枚举常量
select * from areas where id in (4, 5, 6);

-没有关联字段的情况:这样exists对子查询,要么全true,要么全false
select * from areas where id in (select city_id from deals where deals.name = 'xxx');
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。 
在这种情况下,使用exists(或not exists)通常将提高查询的效率。 
举例: 
(低效) 
select ... from table1 t1 where t1.id > 10 and pno in (select no from table2 where name like 'www%'); 
(高效) 
select ... from table1 t1 where t1.id > 10 and exists (select 1 from table2 t2 where t1.pno = t2.no and name like 'www%');
用exists替换distinct: 
当提交一个包含一对多表信息的查询时,避免在select子句中使用distinct. 一般可以考虑用exists替换 
举例: 
(低效) 
select distinct d.dept_no, d.dept_name from t_dept d, t_emp e where d.dept_no = e.dept_no; 
(高效) 
select d.dept_no, d.dept_name from t_dept d where exists (select 1 from t_emp where d.dept_no = e.dept_no); 
exists使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果.
用表连接替换exists: 
通常来说,采用表连接的方式比exists更有效率。 
举例: 
(低效) 
select ename from emp e where exists (select 1 from dept where dept_no = e.dept_no and dept_cat = 'W'); 
SELECT ENAME 
(高效) 
select ename from dept d, emp e where e.dept_no = d.dept_no and dept_cat = 'W';

4.使用连接查询