mysql优化-合理使用IN和EXISTS

分类: MySQL

永远小表驱动大表,即小的数据集驱动大的数据集

ex1:

select * from A where id in (select id from B)

等价于:
for select id from B;
for select * from A where A.id=B.id
当B表的数据集必须小于A表的数据集时,用in 优于exists.

ex2:

select * from A where exits (select 1 from B where B.id=A.id)

等价于:
for select from A;
for select
from B where B.id=A.id
当A表的数据集小于B表的数据集时,用exists优于in.


要注意的是:A表与B表的ID字段应该建立索引
如果查询的两个表大小相当,那么用in和exists差别不大

EXISTS语法

select ... from table where exists(subquery)

将主查询的数据,放到子查询中做条件验证,根据验证结果(TRUE或FALSE)来决定主查询的数据是否得以保留。
说明:
1.EXISTS(subquery)只返回TRUE或FALSE,因此子查询中的select * 也可以是select 1或其他,官方说法是实际执行时会忽略select清单,因此没有区别
2.EXISTS子查询的实际执行过程可能经过了优化而不是我们理解上的逐条对比,如果担忧效率问题,可进行实际检验是否有效率问题
3.EXISTS子查询往往也可以用条件表达式、其他子查询或者JOIN来替代,具体问题具体分析

案例

如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:
例如:表A(小表),表B(大表)

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列的索引。 

相反的

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列的索引。

not in 和not exists如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注