我们有一个很大的表(30万行),其中有很多列(超过80个)。列之一是位字段,用于标记是否删除该行:
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 Index on Bit fields
Should I index a bit field in SQL Server?
查询优化器将永远不会使用此类索引,因为使用这些索引根本不会减少工作集。进行表扫描比读取索引更有效。
如果我们的查询包含WHERE Deleted = 1
子句,它们将很有用。但是他们没有。
那么可以安全地删除所有这些索引吗?
查询优化器是否足够聪明,可以使用索引快速找到Deleted = 1的行,然后将它们从工作集中删除以实现Deleted = 0?
我无法检查系统中所有的查询以确认未使用索引。我想删除这些索引,但是我不想降低系统性能。删除它们会对性能产生负面影响吗?