129

我很好奇以下哪个更有效?

我一直对使用有点谨慎,IN因为我相信 SQL Server 会将结果集变成一个大IF语句。对于大型结果集,这可能会导致性能不佳。对于小型结果集,我不确定两者是否更可取。对于大型结果集,EXISTS效率不是更高吗?

WHERE EXISTS (SELECT * FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)

对比

WHERE bx.BoxID IN (SELECT BoxID FROM Base WHERE [Rank = 2])
4

9 回答 9

156

EXISTS会更快,因为一旦引擎发现命中,它就会停止寻找,因为条件已被证明是正确的。

使用IN,它将在进一步处理之前收集来自子查询的所有结果。

于 2010-01-14T15:53:04.923 回答
44

公认的答案是短视的,而且问题有点松散:

1) 均未明确提及覆盖索引是否存在于左侧、右侧或两侧。

2)都不考虑输入左侧集和输入右侧集的大小。
(这个问题只是提到了一个整体的大结果集)。

我相信优化器足够聪明,可以在由于 (1) 和 (2) 导致成本差异显着时在“in”与“exists”之间进行转换,否则它可能只是用作提示(例如,存在以鼓励使用右侧的可搜索索引)。

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

于 2014-10-09T17:57:14.423 回答
39

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

不过需要注意的是,如果您的查询措辞不当,EXISTS、IN 和 JOIN 有时会返回不同的结果:http ://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210 .aspx

于 2010-08-11T16:08:58.447 回答
8

我会选择 EXISTS over IN,请参见下面的链接:

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

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

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

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

加入:在加入列上加入 2 个结果集。

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

于 2010-01-14T15:51:07.890 回答
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)

查询 2(计划

select * from dt where exists (select 1 from customer c where c.code=dt.customer and c.active=0)
于 2018-12-04T14:31:53.820 回答
3

在这些情况下,执行计划通常是相同的,但是在您了解优化器如何影响索引等的所有其他方面之前,您真的永远不会知道。

于 2010-01-14T15:54:00.507 回答
3

因此,IN 与 EXISTS 不同,也不会产生相同的执行计划。

通常在相关子查询中使用 EXISTS,这意味着您将在外部查询中加入 EXISTS 内部查询。这将添加更多步骤来生成结果,因为您需要解决外部查询连接和内部查询连接,然后匹配它们的 where 子句以连接两者。

通常使用 IN 时不会将内部查询与外部查询相关联,并且只需一步即可解决(在最佳情况下)。

考虑一下:

  1. 如果您使用 IN 并且内部查询结果是数百万行不同的值,那么它可能会比 EXISTS 执行更慢,因为 EXISTS 查询是高性能的(具有与外部查询连接的正确索引)。

  2. 如果您使用 EXISTS 并且与外部查询的连接很复杂(需要更多时间来执行,没有合适的索引),那么查询速度会因外部表中的行数而变慢,有时估计的完成时间可能以天为单位。如果您的给定硬件可以接受行数,或者数据的基数正确(例如,大型数据集中的 DISTINCT 值较少)IN 可以比 EXISTS 执行得更快。

  3. 当您在每个表上有相当数量的行时,将注意到上述所有内容(公平地说,我的意思是超出您的 CPU 处理和/或缓存的 ram 阈值)。

所以答案取决于它。您可以在 IN 或 EXISTS 中编写复杂的查询,但根据经验,您应该尝试将 IN 与一组有限的不同值一起使用,而当您有很多行具有很多不同的值时,您应该尝试使用 EXISTS。

诀窍是限制要扫描的行数。

问候,

马里亚诺

于 2018-05-17T17:55:59.063 回答
1

优化EXISTS,很字面意思;有些东西必须在那里,但您实际上并不需要从相关子查询返回的任何数据。您只是在评估布尔条件。

所以:

WHERE EXISTS (SELECT TOP 1 1 FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)

因为相关子查询是RBAR,所以第一个结果命中使条件为真,不再处理。

于 2014-04-05T18:00:02.963 回答
-1

在我的脑海中并且不能保证是正确的:我相信在这种情况下第二个会更快。

  1. 首先,相关子查询可能会导致为每一行运行子查询。
  2. 在第二个示例中,子查询应该只运行一次,因为不相关。
  3. 在第二个示例中,IN一旦找到匹配项,就会短路。
于 2010-01-14T15:48:34.257 回答