【问题标题】:SQL Server why index is not usedSQL Server 为什么不使用索引
【发布时间】:2011-12-01 13:50:39
【问题描述】:

我在 SQL Server 2008 数据库中有一个下表:

CREATE TABLE [dbo].[Actions](
    [ActionId] [int] IDENTITY(1,1) NOT NULL,    
    [ActionTypeId] [int] NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [Description] [nvarchar](1000) NOT NULL,
    [Comment] [nvarchar](500) NOT NULL,
    [Created] [datetime] NOT NULL,
    [Executed] [datetime] NULL,
    [DisplayText] [nvarchar](1000) NULL,    
    [ExecutedBy] [int] NULL,
    [Result] [int] NULL
)   
CONSTRAINT [PK_Actions] PRIMARY KEY CLUSTERED 
(
    [CaseActionId] ASC
)
) ON [PRIMARY]

GO


CREATE NONCLUSTERED INDEX [IX_Actions_Executed] ON [dbo].[Actions] 
(
    [Executed] ASC,
    [ExecutedBy] ASC
)

执行日期等于“2500-01-01”的 20 000 行和执行日期

当我执行查询时

select CaseActionId, Executed, ExecutedBy, DisplayText from CaseActions
where Executed='2500-01-01'  

查询计划显示对 PK_Actions 执行了聚集索引扫描,并且根本没有使用索引 IX_Actions_Executed

有趣的是我错过了索引提示

/* The Query Processor estimates that implementing the following index could improve the query cost by 99.9901%.
*/

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[Actions] ([Executed])

但是索引已经存在了。

如果要选择 5% 的数据,为什么不使用索引?

【问题讨论】:

    标签: sql sql-server indexing


    【解决方案1】:

    最有可能的是,查询优化器只看到您也在选择 DisplayText - 因此对于在 NC 索引中找到的 20'000 行中的每一行,都需要进行 键查找 进入聚集索引以获取该数据 - 键查找是 昂贵 操作!因此,最终,立即扫描集群索引可能更容易、更有效。

    我敢打赌,如果你在这里运行这个查询:

    select CaseActionId, Executed, ExecutedBy
    from CaseActions
    where Executed='2500-01-01'
    

    然后将使用 NC 索引

    如果您确实需要 DisplayText 并且这是您会经常运行的查询,也许您应该将该列作为叶级的额外列包含在索引中:

    DROP INDEX [IX_Actions_Executed] 
    
    CREATE NONCLUSTERED INDEX [IX_Actions_Executed] 
    ON [dbo].[Actions]([Executed] ASC, [ExecutedBy] ASC)
    INCLUDE([DisplayText])
    

    这将使您的 NC 索引成为覆盖索引,即它可以返回查询所需的所有列。如果您使用此覆盖索引再次运行原始查询,我很确定 SQL Server 的查询优化器确实会使用它。如果 NC 索引是一个覆盖索引,则使用任何 NC 索引的概率会显着增加,例如一些查询可以仅从 NC 索引中获取所需的所有列,而无需进行键查找。

    缺少的索引提示有时会有点误导 - 还有一些已知的错误会导致 SQL Server Mgmt Studio 不断推荐已经存在的索引.....不要在这些上押太多钱索引提示!

    【讨论】:

    • 是的,您对 DisplayText 的看法是正确的。您说 20000 键查找比扫描整个聚集索引更昂贵?好的,谢谢你的信息。
    • @WaldiMen:测试一下! :-) 您可以通过WITH (INDEX(IX_Actions_Executed)) 强制 SQL Server 使用索引 - 比较执行计划、执行时间和 I/O 统计信息。另外:尝试 covering index 方法 - 如果包含 DisplayText 列,我很确定它会被使用....
    猜你喜欢
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    相关资源
    最近更新 更多