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.使用连接查询