将索引扫描转换为索引查找

Turn index scan to an index seek

我已将索引添加到 table 以停止 table 扫描。现在它扫描索引而不是 table,为什么它不执行索引查找?

CREATE PROCEDURE [dbo].[GetPeople]
(
    @PlaceIDs [dbo].[Integers] READONLY,
    @RoleGroupIDs [dbo].[Integers] READONLY
)

AS
BEGIN
    SET NOCOUNT ON;
    SELECT
        PTS.PersonToSiteID,
        PTS.SiteID,
        PTS.PersonID,
        P.PersonID,
        P.GivenName,
        P.FamilyName,
        P.Email,
        P.LandlineNumber,
        P.MobileNumber,
        R.RoleTypeID
    FROM 
        [dbo].[PeopleToPlaces] PTS
        INNER JOIN (Select DISTINCT Identifier FROM @PlaceIDs) Pl ON PTS.PlaceID = Pl.Identifier
        INNER JOIN [dbo].[People] P ON P.PeopleID = PTS.PeopleID 
        INNER JOIN [dbo].[Role] R ON R.RoleID = P.RoleID
        INNER JOIN (Select DISTINCT Identifier FROM @RoleGroupIDs) RG ON R.RoleGroupID = RG.Identifier
END

我有一个关于 People table 的覆盖索引,并且在测试时添加了 Distinct 子查询。有一个索引覆盖了 PTS table 的连接和标识符字段,因为 UDT 都是与它们连接到的类型相匹配的整数。与 JOIN 相比,我还尝试了 SELECT IN,但找不到避免索引扫描的方法

目前已将其用作资源 - https://www.red-gate.com/simple-talk/sql/performance/identifying-and-solving-index-scan-problems/

您的查询没有 WHERE 过滤子句;它要求那个大连接的结果集中的所有记录。

如果您只需要一个或非常小的行,查询规划器会选择 index seek 而不是 index scan你的结果集。 索引扫描 是一个两步过程:首先它寻找它需要的第一行(可能是索引中的第一行)。然后它按顺序扫描索引以获取所需的其余行。

扫描覆盖索引是获取多行结果集的有效方法:可以从索引中满足查询,因此查询计划器不必在索引和 table 数据本身。

这里一切都很好。