与IN子句一起使用时,未绑定的结果集是否比具有连接的查询更高效?

时间:2011-07-21 15:29:13

标签: sql-server performance

使用IN子句中的子查询,我最好返回大量结果(10,000多行)或使用表连接来限制结果吗?

例如:

select * from Units u
  inner join pm_Properties p on p.PropertyId = u.PropertyId
  where p.State = 'CA'
  and u.UnitId in (select UnitId from Leases l where l.IsActive = 1)

VS

select * from Units u
  inner join pm_Properties p on p.PropertyId = u.PropertyId
  where p.State = 'CA'
  and u.UnitId in (select UnitId from Leases l 
    inner join Units u on u.UnitId = l.UnitId 
    inner join Properties p on p.PropertyId = u.PropertyId 
    where l.IsActive = 1 and p.State = 'CA')

在这两种情况下,我都希望返回与属性连接的单位结果。我只是对IN语句的性能差异感到好奇。此外,如果重要,服务器是MS SQL 2008 R2。

3 个答案:

答案 0 :(得分:2)

使用第一个(除非出于某种原因出现性能问题)。

第二个是提供SQL服务器能够自行解决的冗余信息 - 您所做的只是增加查询的复杂性,增加了制定执行计划的成本并增加了它赢得的机会找不到最佳方案。

答案 1 :(得分:0)

我认为让优化器完成其工作的最有效方法是避免使用带有子查询的两个版本。为什么不呢?

SELECT * 
  FROM Units AS u
  INNER JOIN pm_Properties AS p
  ON p.PropertyId = u.PropertyId
  INNER JOIN Leases AS l
  ON l.UnitId = u.UnitId
  AND l.IsActive = 1
  WHERE p.State = 'CA';

根据JNK的建议,另一个替代方案如下(但正如我所建议的,如果CA中有很大比例,可能会有大量的I / O检查有效租约):

SELECT *
    FROM Units AS u
    INNER JOIN pm_Properties AS p
    ON p.PropertyId = u.PropertyId
    WHERE p.State = 'CA'
    AND EXISTS
    (
      SELECT 1 FROM Leases AS l
         WHERE l.UnitId = u.UnitId
         AND l.IsActive = 1
    );

当然,您了解您的数据,索引,硬件,使用模式等。最有效的方式来确定您“最好”的路线是测试它们你自己 - 这会给你一个比你在这里问的人更可靠的答案。对任何人都没有冒犯,但有太多的变数无法做出一揽子陈述。

另外 - 这只是一个例子 - 制作表别名单位 - >的重点是什么?单元?你输入了4个额外的字符以避免输入一个字符 - 如果你计划在查询中引用单位超过4次,这可能是有意义的,但特别是在这种情况下我宁愿做一个更短的别名。

答案 2 :(得分:0)

正如JNK所暗示的,这取决于。

这取决于您的连接条件必须有多复杂,以及每个表相对于其他表的行数。我认为在“正常”情况下,没有IN子句内部连接的第一个示例会更快,但这会因我提到的因素而异。

所以,如果你真的想要绝对优化性能,我会对它们进行测试,然后根据你的特定情况更好地投入生产。但是,如果他们甚至接近我会更喜欢第一个(我认为无论如何我会在大多数用例中获胜)。优化器更容易使用,更重要的是它更容易阅读,这意味着它更容易维护。