3

如果我像这样搜索用户:

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?

4

2 回答 2

4

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

您可以通过以下方式强制搜索:

from userprofile with (forceseek)
于 2013-05-09T16:04:24.847 回答
1

强迫它寻找不一定会更快,它可能会慢得多。

如果您重写查询以使用 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
)

肯定不会慢的。

于 2013-05-09T16:13:17.570 回答