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

Posted

技术标签:

【中文标题】将索引扫描转换为索引查找【英文标题】:Turn index scan to an index seek 【发布时间】:2021-06-09 14:06:16 【问题描述】:

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

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 表上有一个覆盖索引,并在测试时添加了 Distinct 子查询。有一个索引覆盖了 PTS 表的连接和 UDT 中的 Identifier 字段都是与它们连接的类型匹配的整数。与 JOIN 相比,我还尝试了 SELECT IN,但找不到避免索引扫描的方法

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

【问题讨论】:

您使用的是哪个 dbms? (MS SQL Server?) 除非您的索引包括您在表中使用的所有列,否则 SQL Server 很可能会确定执行表扫描仍然比使用索引更有效。 您需要提供您的实际执行计划(请参阅 pastetheplan),它可能取决于各种因素,例如基数、估计等 “索引扫描”不是问题。这可能是您查询的最佳选择,特别是如果我们认为您的查询没有过滤。 对不起它的 MS SQL Server 【参考方案1】:

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

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

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

这里一切顺利。

【讨论】:

以上是关于将索引扫描转换为索引查找的主要内容,如果未能解决你的问题,请参考以下文章

Mysql学习---索引的学习 180101

mysql 避免索引失效

将聚簇索引扫描优化为聚簇索引查找

索引的访问-SQL Server

为啥这是索引扫描而不是索引查找

非唯一键查找和索引范围扫描有啥区别?