Sql中的in和与not in, exists与not exists区别和性能分析
1、in和exists
- in把外表和内标作Hash连接
- exists对外表作loop循环,每次loop循环再对内表进行查询
使用:
- 两张表大小相当。用in和exists差别不大
- 两张表一大一小(相对而言),子查询大表,用exists;子查询小表,用in;
例如:
A小表,B大表
select * from A where col in(select * from B) -->效率低,用到了A表上col列的索引;
select * from A where exists(select * from B where col = A.col) -->效率高,用到了B表上col列的索引。
select * from B where col in(select * from A) -->效率高,用到了B表上col列的索引
select * from B where exists(select * from A where col = B.col) -->效率低,用到了A表上col列的索引。
可以理解为in,是先进行外查询,然后再根据外查询的结果进入子查询中找结果。exists,是先进行内查询,然后根据子查询的结果向外面找符合的结果。 仅作为理解,真实的运行过程笔者仍需学习。
使用上exists的使用,前面的where语句没有属性赋值,因为exists返回的是一个结果集,而不应该将这个结果集赋值给某个属性。而且一般使用exists最终外查询会用到内循环返回的结果集,也就是用到内循环的索引,所以一般exists查找的结果为整张表,即"select * ",还要带上where条件进行限定。
2、not in 和 not exists
简短说,not in 和 not exists有区别。
create table t1(c1 int, c2 int);
create table t2(c1 int, c2 int);
insert into t1 values(1, 2);
insert into t1 values(1, 3);
insert into t2 values(1, 2);
insert into t2 values(1, null);
select * from t1 where c2 not in(select c2 from t2); -->执行结果:无
select * from t1 where not exists(select * from t2 where t2.c2 = t1.c2) -->执行结果:1 3
根据结果可以分析,not in出现了不期望的结果集,存在逻辑错误。所以尽量不要用not in(会调用子查询),而尽量使用not exists(会调用关联子查询)。
如果子查询中存在一条记录含有空值,则查询将不返回任何记录。
如果子查询字段有非空限制,这是可以用not in。
使用not in,那么对内外表都会进行全表扫描,没有用到索引;而not exists的子查询依然可以使用。所以无论哪个表大,用not exists都比not in快。
3、in 与 = 的区别
select name from student where name in('zhang','wang','zhao');
select name from student where name='zhang' or name='wang' or name='zhao'
结果相同。
4、exists执行流程分析
select * from t1 where exists ( select null from t2 where y = x )
理解为:
for x in ( select * from t1 ) loop
if ( exists ( select null from t2 where y = x.x ) then
OUTPUT THE RECORD
end if
end loop
网友评论