[TEST1@orcl#22-12月-10] SQL>select * from t9 where sal in (select id from t8);
YEAR SAL
---------- ----------
2000 10
这个句子与下面的句子等价:
[TEST1@orcl#22-12月-10] SQL>select t9.* from t9,(select distinct id from t8) t8 where t8.id=t9.sal;
select distinct id from t8 会被使用到索引。
关于exists:
[TEST1@orcl#22-12月-10] SQL>select * from t9 where exists (select id from t8 where t8.id=t9.sal);
YEAR SAL
---------- ----------
2000 10
这相当于下面的句子
for v in (select * from t9) loop
if(exists(select null from t8 where t8.id=t9.sal)) then
output the record;
end if;
end loop;
分析:
假设t8表数据量很大
那么select id from t8 将会耗费很长时间。
而select null from t8 where t8.id=t9.sal 执行速度非常快(这主要得益于t8表id列上面的索引)。
此时t1表的数据量相对较少。那么尽管select * from t9 是全表扫描,再从t8上使用索引查询,但是仍然比索引查询t9,再全表扫描t8表要快上很多。
因此可以得出exists适用于大数据量,in适用于小数据量了。
如果子查询和外表都很大,那么in和exists效率差不多。查询速度就必须依赖于其它因素了。
那么从上面还能得出什么结论呢?如果t8表中游空值又会发生什么事情?
其实可以从上面的语句中看出来。
[TEST1@orcl#23-12月-10] SQL>insert into t8 values(null);
已创建 1 行。
[TEST1@orcl#23-12月-10] SQL>insert into t9 values(2004,null);
已创建 1 行。
[TEST1@orcl#23-12月-10] SQL>commit;
提交完成。
[TEST1@orcl#23-12月-10] SQL>select * from t9 where sal in (select id from t8);
YEAR SAL
---------- ----------
2000 10
[TEST1@orcl#23-12月-10] SQL>select * from t9 where exists (select id from t8);
YEAR SAL
---------- ----------
2000 10
2001 20
2002 30
2003 40
2004
in不包含空值,而exists包含空值。
的结果是相同的。