我很好奇以下哪一项会更有效率?
我一直对使用IN
持谨慎态度,因为我相信SQL Server会将结果集转换为大IF
语句。对于大的结果集,这可能导致性能不佳。对于小结果集,我不确定是否更可取。对于大型结果集,EXISTS
不会更有效吗?
WHERE EXISTS (SELECT * FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)
VS
WHERE bx.BoxID IN (SELECT BoxID FROM Base WHERE [Rank = 2])
答案 0 :(得分:130)
EXISTS
会更快,因为一旦发动机发现了撞击,它就会退出,因为条件证明是正确的。
使用IN
,它将在进一步处理之前从子查询中收集所有结果。
答案 1 :(得分:35)
我已经对SQL Server 2005和2008进行了一些测试,并且EXISTS和IN都返回了完全相同的实际执行计划,正如其他人所说的那样。优化器是最佳的。 :)
要注意的是,如果你没有恰当地表达你的查询,EXISTS,IN和JOIN有时会返回不同的结果:http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx
答案 2 :(得分:35)
接受的答案是短视的,问题有点松散:
1)两者都没有明确提及是否存在覆盖指数 左,右或两侧。
2)既没有考虑输入左侧设置的大小和 输入右侧设置。
(问题只是提到了一个整体的大型结果集)。
我相信优化器足够聪明,当由于(1)和(2)导致显着的成本差异时,在“in”和“exists”之间进行转换,否则它可能仅用作提示(例如,存在于鼓励在右侧使用可寻找的指数)。
两个表单都可以在内部转换为连接表单,反转连接顺序,并根据估计的行数(左和右)和左,右或两者的索引存在运行循环,散列或合并侧上。
答案 3 :(得分:3)
我会在IN上使用EXISTS,请参阅以下链接:
答案 4 :(得分:3)
在这些情况下,执行计划通常是相同的,但在你看到优化器如何影响索引的所有其他方面等之前,你真的永远不会知道。
答案 5 :(得分:2)
因此,IN与EXISTS不同,也不会产生相同的执行计划。
通常在相关子查询中使用EXISTS,这意味着您将使用外部查询加入EXISTS内部查询。这将添加更多步骤来生成结果,因为您需要解决外部查询连接,然后内部查询连接匹配其where子句以加入两者。
通常使用IN而不将内部查询与外部查询相关联,并且只能在一个步骤中解决(在最佳情况下)。
考虑一下:
如果使用IN并且内部查询结果是数百万行不同的值,则鉴于EXISTS查询是高性能的(具有与外部查询连接的正确索引),它可能会执行SLOWER而不是EXISTS。
如果使用EXISTS并且外部查询的连接很复杂(需要更多时间来执行,没有合适的索引),它将使查询减慢外表中的行数,有时估计时间为完成可以在几天内完成。如果给定硬件的行数是可接受的,或者数据的基数是正确的(例如,大数据集中的DISTINCT值较少)IN的执行速度可能比EXISTS快。
当每个表上有相当数量的行时,会注意到以上所有内容(通过公平,我的意思是超出CPU处理和/或缓存的ram阈值)。
所以答案是ANSWER。您可以在IN或EXISTS中编写复杂查询,但根据经验,当您有许多具有大量不同值的行时,您应该尝试使用IN和一组有限的不同值和EXISTS。
诀窍是限制要扫描的行数。
此致
MarianoC
答案 6 :(得分:1)
优化EXISTS
,非常字面;只需要存在某些东西,但实际上并不需要从相关子查询返回任何数据。您只是在评估布尔条件。
所以:
WHERE EXISTS (SELECT TOP 1 1 FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)
因为相关的子查询是RBAR
,所以第一个结果命中使条件为真,并且不再进行处理。
答案 7 :(得分:1)
这里有许多误导性的答案,包括被高度评价的答案(尽管我不认为他们的操作会带来伤害)。 简短的答案是:这些都是相同的。
(T-)SQL语言中有很多关键字,但是最后,真正在硬件上发生的唯一事情就是执行查询计划中看到的操作。
当调用[NOT] IN
且[NOT] EXISTS
时,我们执行的关系(数学理论)操作是半联接(使用NOT
时是反联接)。相应的sql-server操作具有相同的名称并非巧合。在任何地方都没有提及IN
或EXISTS
的操作-仅(反)半联接。因此,没有办法在逻辑上等效的IN
与EXISTS
选择会影响性能,因为只有一种方法(反)半联接执行操作可以获取结果。 。
一个例子:
查询1(plan)
select * from dt where dt.customer in (select c.code from customer c where c.active=0)
查询2(plan)
select * from dt where exists (select 1 from customer c where c.code=dt.customer and c.active=0)
答案 8 :(得分:-1)
离开我的头顶并且不能保证是正确的:我相信在这种情况下第二个会更快。
IN
会在找到匹配后立即短路。