首页 > 解决方案 > BIT 非选择性列上的 SQL Server 索引

问题描述

我们有很多列(80+)的非常大的表(300k 行)。其中一列是一个位字段,用于标记该行是否被删除:

CREATE TABLE [dbo].[tblProject]
(
    [Id] [INT] IDENTITY(1,1) NOT NULL,
    ...
    [Deleted] [BIT] NOT NULL,

    CONSTRAINT [PK_tblProject] 
        PRIMARY KEY CLUSTERED ([Id] ASC) ON [PRIMARY]
)

一些不再与我们合作的开发人员在Deleted列上创建了 3 个索引:

CREATE NONCLUSTERED INDEX [IX_tblProject_Deleted] 
ON [dbo].[tblProject] ([Deleted] ASC)
INCLUDE ([Id], [FK1Id], [FK2Id], [FK3Id], [SomeDecimalColumn]) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [IX_tblProject_Deleted2] 
ON [dbo].[tblProject] ([Deleted] ASC)
INCLUDE ([Id], [FK1Id], [FK2Id], [FK4Id], [FK5Id]) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [IX_tblProject_Deleted3] 
ON [dbo].[tblProject] ([Deleted] ASC)
INCLUDE ([Id], [FK1Id], [FK2Id], [FK4Id]) ON [PRIMARY]

我的第一个问题是——第三个索引似乎完全被索引 2 覆盖了。我说这样的索引没有带来任何有价值的东西并且可以被删除是对的吗?

列的数据分布Deleted如下所示:

99.9% rows contain 0
0.1% rows contain 1

我们有很多tblProject关于各种外键的查询,它们都包含WHERE Deleted = 0子句。如您所见,此谓词几乎不会从工作集中删除任何行。

据我所知和以下链接:

位字段上的 Sql Server 索引

我应该索引 SQL Server 中的位字段吗?

位列上的索引

查询优化器永远不会使用这些索引,因为这些索引的使用根本不会减少工作集。执行表扫描比读取索引更有效。

WHERE Deleted = 1如果我们的查询包含子句,它们将很有用。但他们没有。

那么所有这些索引都可以安全删除吗?

或者查询优化器是否足够聪明,可以使用索引快速找到 Deleted=1 的行,然后将它们从工作集中删除以实现 Deleted=0?

我无法检查系统中的所有查询以确认未使用索引。我想删除这些索引,但我不想降低系统性能。删除它们会对性能产生负面影响吗?

标签: sql-serverindexing

解决方案


推荐阅读