in和exists的区别与执行效率问题解析
文章作者 100test 发表时间 2008:04:02 14:23:53
来源 100Test.Com百考试题网
in可以分为三类:
1、形如0select * from t1 where f1 in ( &.apos;a &.apos;, &.apos;b &.apos;),应该和以下两种比较效率
0select * from t1 where f1= &.apos;a &.apos; or f1= &.apos;b &.apos;
或者 0select * from t1 where f1 = &.apos;a &.apos; union all 0select * from t1 f1= &.apos;b &.apos;
你可能指的不是这一类,这里不做讨论。
2、形如0select * from t1 where f1 in (0select f1 from t2 where t2.fx= &.apos;x &.apos;),
其中子查询的where里的条件不受外层查询的影响,这类查询一般情况下,自动优化会转成exist语句,也就是效率和exist一样。
3、形如0select * from t1 where f1 in (0select f1 from t2 where t2.fx=t1.fx),
其中子查询的where里的条件受外层查询的影响,这类查询的效率要看相关条件涉及的字段的索引情况和数据量多少,一般认为效率不如exists.
除了第一类in语句都是可以转化成exists 语句的,一般编程习惯应该是用exists而不用in.
A,B两个表,
(1)当只显示一个表的数据如A,关系条件只一个如ID时,使用IN更快:
0select * from A where id in (0select id from B)
(2)当只显示一个表的数据如A,关系条件不只一个如ID,col1时,使用IN就不方便了,可以使用EXISTS:
0select * from A
where exists (0select 1 from B where id = A.id and col1 = A.col1)
(3)当只显示两个表的数据时,使用IN,EXISTS都不合适,要使用连接:
0select * from A left join B on id = A.id
所以使用何种方式,要根据要求来定。
这是一般情况下做的测试:
这是偶的测试结果:
set statistics io on 0select * from sysobjects where exists (0select 1 from syscolumns where id=syscolumns.id) 0select * from sysobjects where id in (0select id from syscolumns ) set statistics io off |
(47 行受影响)
表 &.apos;syscolpars &.apos;。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 2 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 &.apos;sysschobjs &.apos;。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
(44 行受影响)
表 &.apos;syscolpars &.apos;。扫描计数 47,逻辑读取 97 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 &.apos;sysschobjs &.apos;。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
set statistics io on 0select * from syscolumns where exists (0select 1 from sysobjects where id=syscolumns.id) 0select * from syscolumns where id in (0select id from sysobjects ) set statistics io off |
(419 行受影响)
表 &.apos;syscolpars &.apos;。扫描计数 1,逻辑读取 10 次,物理读取 0 次,预读 15 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 &.apos;sysschobjs &.apos;。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
(419 行受影响)
表 &.apos;syscolpars &.apos;。扫描计数 1,逻辑读取 10 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 &.apos;sysschobjs &.apos;。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
测试结果(总体来讲exists比in的效率高):
效率:条件因素的索引是非常关键的
把syscolumns 作为条件:syscolumns 数据大于sysobjects