【问题标题】:Why inner join with a filtered table more slowly than that without filtering?为什么过滤表的内连接比不过滤的慢?
【发布时间】:2012-02-29 01:24:30
【问题描述】:

WINDOWS 2008 上的 SQL Server 2008

请比较以下sql:

1.

select count(*) 
from Trades t 
inner join UserAccount ua on ua.AccID = t.AccID

2.

select count(*) 
from Trades t 
inner join (
    select * 
    from UserAccount ua 
    where ua.UserID = 1126
) as theua on theua.AccID = t.AccID

3.

select count(*) 
from Trades t 
inner join UserAccount ua on ua.AccID = t.AccID 
where ua.UserID=1126

Given Trades 有数百万行,而 UserAccount 是一个很小的表。而且 AccID 可以重复。

执行结果:

  1. 234734792
  2. 8806144
  3. 8806144

我预计2号至少可以和1号一样快,但实际上它比3号慢得多甚至慢得多 耗时:

  1. 2 秒
  2. 10 秒
  3. 8 秒

有人可以解释原因吗?当我需要像 UserID=1126 这样的过滤器时,是否可以让它更快?

【问题讨论】:

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


    【解决方案1】:
    1. 是最快的,因为它的 where 条件最少。
      (缺少的用户 ID)

    2. 是最慢的,因为它有一个必须为每个连接执行的内部选择
      顺便说一句:永远不要这样做

    3. 由于额外的 where 条件 (UserID) 而比 #1 慢。 这是您要使用的查询。
      (您也可以在加入后直接将“where”替换为“and”)

    您是否设置了外键

    同时确保您拥有适当的索引(即:AccID 和 UserID)。

    在 SSMS 中,使用 执行计划 运行查询,它会显示您应该创建的查询/索引中潜在的低效率。

    在执行计划中,您应该注意诸如表扫描之类的内容。您想看到的是 seeks

    【讨论】:

    • 至于2,我可以选择它到一个临时表中,然后与该临时表进行内部连接,这样会更快吗?
    • 您想要查询 #3,这是最好的查询,但您可能缺少影响速度的索引。
    • 我在 UserAccount 表中有一个关于 UserID 和 AccID 的索引,而在 Trades 表中没有。
    • 你有外键吗?你检查执行计划了吗?
    • @BobL,我想说如果您想看到性能优势,您需要在交易表中的 t.AccID 上建立索引。正如 b1naryj 建议的那样,这是最能帮助你的。在添加索引之前和之后检查执行计划,就像他说的那样。外键将有助于参考完整性,但不利于性能。不过当然应该考虑它们。
    猜你喜欢
    • 2020-10-20
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    • 2022-11-23
    • 1970-01-01
    • 2010-10-13
    • 2023-03-19
    相关资源
    最近更新 更多