【问题标题】:Why does SQL Server perform a clustered scan when IN clause has a subquery?为什么当 IN 子句有子查询时 SQL Server 会执行集群扫描?
【发布时间】:2013-05-04 04:25:48
【问题描述】:

如果我这样搜索用户:

SELECT *
FROM userprofile
WHERE userid IN (1, 2, 3)

执行计划显示 UserProfile 正在使用 Clustered Index Seek

如果我将 IN 子句更改为使用子查询:

SELECT *
FROM userprofile
WHERE userid IN (
    SELECT DISTINCT senders.UserId
    FROM messages m
    JOIN UserMessages recipients ON recipients.MessageId = m.MessageId
    JOIN UserMessages senders ON senders.MessageId = m.MessageId
    WHERE recipients.TypeId = 2
        AND recipients.UserId = 1
        AND senders.UserId <> 1
        AND senders.TypeId = 1 
)

执行计划显示子查询正在使用聚集索引搜索,但 UserProfile 外部查询正在使用聚集索引扫描。

我怎样才能这样写,以便内部和外部查询都使用 Seeks?

【问题讨论】:

    标签: sql sql-server performance tsql indexing


    【解决方案1】:

    如果行数较低,则一组查找仅比完整扫描便宜。 SQL Server 是相当保守的,所以如果有机会找到很多记录,它更喜欢扫描。在您的示例中,很明显 userId in (1,2,3) 不会返回很多行。但是对于子查询,SQL Server 可能无法分辨。

    您可以使用以下命令强制搜索:

    from userprofile with (forceseek)
    

    【讨论】:

    • 完全正确 - 由于优化器无法决定内部子查询会产生多少行,所以它没有使用基本上相当于 key lookups 的内容(索引查找聚集索引) 来查找所有匹配的行 - 它只是默认使用聚集索引 scan 代替。
    【解决方案2】:

    强制它去寻找不一定会更快,它可能会慢很多。

    如果您重写查询以使用 EXISTS 而不是 IN,它可能会更快:

    select * from userprofile    -- << note that '*' is slow here
    where EXISTS(
      select * from messages m   -- << but '*' is not slow here
      join UserMessages recipients on recipients.MessageId = m.MessageId
      join UserMessages senders on senders.MessageId = m.MessageId
      where recipients.TypeId = 2
        and recipients.UserId = 1 
        and senders.UserId <> 1 
        and senders.TypeId = 1
        and senders.UserId = userprofile.userid
    )
    

    肯定不会慢的。

    【讨论】:

    • 除非查询优化器真的很聪明,否则exists 将导致userprofile 中的每一行都有一个子查询。这可能比聚集索引扫描慢得多。
    • 不会超过原来的IN(..)。事实上,所有现代专业 SQL DBMS 都足够聪明,可以优化这一点,如果可能的话。无论如何,在 SQL Server 中几乎没有IN(..) 比相应的EXISTS(..) 更快的情况。所以试试看。
    猜你喜欢
    • 2011-03-01
    • 2013-10-09
    • 2016-10-24
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-28
    相关资源
    最近更新 更多