【问题标题】:Should I avoid IN() because slower than EXISTS() [duplicate]我应该避免 IN() 因为比 EXISTS() 慢吗?
【发布时间】:2012-03-29 17:28:38
【问题描述】:

可能重复:
SQL Server IN vs. EXISTS Performance

我应该避免 IN() 因为比 EXISTS() 慢吗?

SELECT * FROM TABLE1 t1 WHERE EXISTS (SELECT 1 FROM TABLE2 t2 WHERE t1.ID = t2.ID)

VS

SELECT * FROM TABLE1 t1 WHERE t1.ID IN(SELECT t2.ID FROM TABLE2 t2)

根据我的调查,我设置了 SHOWPLAN_ALL。我得到相同的执行计划和估算成本。使用索引(pk),在两个查询中查找。没有不同。

还有哪些其他情况或其他情况可以使两个查询的结果大不相同?优化器是否对我进行了优化以获得相同的执行计划?

【问题讨论】:

  • “还有哪些其他场景或其他情况会对这两个查询产生重大影响” - 执行计划取决于很多事情,所以你总是需要检查它
  • @DavidHall 谢谢你,我会看帖子的。

标签: sql sql-server sql-server-2008


【解决方案1】:

两者都不做。这样做:

SELECT DISTINCT T1.* 
FROM TABLE1 t1
JOIN TABLE2 t2 ON t1.ID = t2.ID;

这将在数量级上胜过其他任何事情。

【讨论】:

  • 如果 TABLE1TABLE2 之间存在 1..M 关系,这会给你一个不同的结果。
  • @MikaelEriksson 你是对的。我添加了DISTINCT。谢谢。
  • @Bohemian 谢谢你的回答。如果你足够好心地指出我什么时候应该使用 IN()。或者我应该尽可能避免 IN() 吗?
  • @Pongsathon.keng:Bohemian 的方法在 MySQL 上表现更好,但在 SQLServer 上却不行——请参阅 Diego 的回答。一般来说,最好使用 EXISTS 而不是 IN,除非你有一个值列表而不是一个表 - 例如:SELECT * FROM TABLE1 WHERE ID IN (1, 7, 16);
【解决方案2】:

两个查询将产生相同的执行计划(假设没有创建索引):两次表扫描和一个嵌套循环(连接)。

Bohemian 建议的连接将执行哈希匹配而不是循环,我一直听说(这里有一个证明:Link)是最糟糕的连接。

在 IN 和 EXIST(您的实际问题)中,EXISTS 表现更好(看看:Link

【讨论】:

    【解决方案3】:

    如果您的表 T2 有很多记录,则 EXISTS 是更好的方法,因为当您的数据库找到符合您要求的记录时,条件将被评估为 true 并停止从 T2 进行扫描。但是,在 IN 子句中,您正在为 table1 中的每一行扫描 Table2。 当您有一堆值或子查询中的值很少时,IN 比 Exists 更好。 扩展一点我的答案,基于问汤姆的回答: 在带有 in 的 Select 中,例如:

    Select * from T1 where x in ( select y from T2 )
    

    通常被处理为:

    select * 
      from t1, ( select distinct y from t2 ) t2
     where t1.x = t2.y;
    

    子查询被评估、区分、索引(或散列或排序),然后连接到原始表(通常)。

    在存在的查询中,例如:

    select * from t1 where exists ( select null from t2 where y = x )
    

    处理起来更像:

    for x in ( select * from t1 )
       loop
          if ( exists ( select null from t2 where y = x.x )
          then 
             OUTPUT THE RECORD
          end if
       end loop
    

    它总是会导致对 T1 进行全面扫描,而第一个查询可以使用 T1(x) 上的索引。

    什么时候存在合适和合适的地方?

    1. EXISTS 当...时使用 EXISTS
    2. 在以下情况下使用 IN... 子查询的结果很小 -- 那么 IN 通常更合适。
    3. 如果子查询和外部表都很大——其中一个可能工作得和另一个一样好——取决于索引和其他因素。

    【讨论】:

    • 对最后一个语句不是很清楚......最好使用一堆值或几个值。唯一的原因是我现在因为缺乏明确性而投反对票。更新您的回复,如果提供更多详细信息,我会尝试投票。
    • 好的.. 我试着改进我的答案
    猜你喜欢
    • 2012-10-14
    • 2011-04-15
    • 2014-10-24
    • 2022-12-16
    • 1970-01-01
    • 2010-09-23
    • 2020-12-15
    • 2010-10-15
    • 2020-10-05
    相关资源
    最近更新 更多