SQL Server IN与EXISTS性能

Ran*_*der 112 sql-server sql-server-2005 exists query-performance sql-in

我很好奇以下哪一项会更有效率?
我一直对使用有点谨慎,IN因为我相信SQL Server会将结果集转化为一个大的IF声明.对于大的结果集,这可能导致性能不佳.对于小结果集,我不确定是否更可取.对于大型结果集,EXISTS效率会不会更高?

WHERE EXISTS (SELECT * FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)
Run Code Online (Sandbox Code Playgroud)

WHERE bx.BoxID IN (SELECT BoxID FROM Base WHERE [Rank = 2])
Run Code Online (Sandbox Code Playgroud)

kei*_*en7 135

EXISTS将会更快,因为一旦发动机发现了撞击,它就会退出,因为条件证明是正确的.
使用IN它将在进一步处理之前收集子查询的所有结果.

  • 这曾经是真实的,但在当前版本(至少2008年)中,优化器更加智能......它实际上就像EXISTS()一样对待IN(). (69认同)
  • @Aaron - 是的,通常优化器会在内部产生更好的计划.但是,在更复杂的情况下,依赖内部快捷方式可能会有害. (11认同)
  • 那是个很好的观点.IN语句要求SQL Server生成完整的结果集,然后创建一个我认为的大IF语句. (3认同)
  • 这完全是错的.那是在2010年,现在仍然是. (2认同)
  • IN和EXISTS具有完全相同的查询计划和IO。没有理由认为它们在性能上有所不同。检查您的时间统计并改善自己 (2认同)

Ada*_*ger 37

我已经对SQL Server 2005和2008进行了一些测试,并且EXISTS和IN都返回了完全相同的实际执行计划,正如其他人所说的那样.优化器是最佳的.:)

但要注意的是,EXISTS,IN和JOIN有时会返回不同的结果,如果你不恰当地表达你的查询:http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210的.aspx


cro*_*sek 37

接受的答案是短视的,问题有点松散:

1)没有明确提及左侧,右侧或两侧是否存在覆盖指数.

2)既没有考虑输入左侧设置和输入右侧设置的大小.
(这个问题只是提到了一个整体的大结果集).

我认为优化器足够智能,当由于(1)和(2)导致显着的成本差异时,在"in"和"exists"之间进行转换,否则它可能只是用作提示(例如,存在鼓励使用一个可寻找的右侧索引).

两种形式都可以在内部转换为连接形式,反转连接顺序,并作为循环,散列或合并运行 - 基于估计的行数(左和右)和左侧,右侧或两侧的索引存在.

  • 不知道为什么这个优秀的答案没有得到更多的关注.了解双方的指数/结构可能会影响我同意.说得好. (3认同)

Tan*_*ner 7

我会在 IN 上使用 EXISTS,请参阅以下链接:

SQL Server:JOIN vs IN vs EXISTS - 逻辑差异

有一个常见的误解,认为 IN 在返回结果方面与 EXISTS 或 JOIN 的行为相同。这是不正确的。

IN:如果指定值与子查询或列表中的任何值匹配,则返回 true。

存在:如果子查询包含任何行,则返回 true。

联接:在联接列上联接 2 个结果集。

博客信用:https : //stackoverflow.com/users/31345/mladen-prajdic


Geo*_*tis 6

这里有许多误导性的答案,包括高度赞扬的答案(尽管我不相信他们的操作意味着伤害)。简短的回答是:这些都是一样的。

(T-)SQL 语言中有很多关键字,但最终真正发生在硬件上的只是执行查询计划中看到的操作。

我们在调用[NOT] IN和时执行的关系(数学理论)操作[NOT] EXISTS是半连接(使用时为反连接NOT)。对应的sql-server操作同名并非巧合。没有提及INEXISTS任何地方的操作- 只有(反)半连接。因此,逻辑上等效的INvsEXISTS选择不可能影响性能,因为只有一种且唯一的方法,即(反)半连接执行操作,来获得它们的结果

一个例子:

查询 1(计划

select * from dt where dt.customer in (select c.code from customer c where c.active=0)
Run Code Online (Sandbox Code Playgroud)

查询 2(计划

select * from dt where exists (select 1 from customer c where c.code=dt.customer and c.active=0)
Run Code Online (Sandbox Code Playgroud)