为什么当 IN 子句有子查询时 SQL Server 会执行聚集扫描?

Jon*_*ith 4 sql t-sql sql-server indexing performance

如果我像这样搜索用户:

SELECT *
FROM userprofile
WHERE userid IN (1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

执行计划显示 UserProfile 正在使用聚集索引查找

如果我更改 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 
)
Run Code Online (Sandbox Code Playgroud)

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

我该如何编写这个以便内部和外部查询都使用 Seeks?

And*_*mar 5

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

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

from userprofile with (forceseek)
Run Code Online (Sandbox Code Playgroud)