Indexing 软删除-使用IsDeleted标志或单独的joiner表?

Indexing 软删除-使用IsDeleted标志或单独的joiner表?,indexing,sql-server-2008-r2,soft-delete,Indexing,Sql Server 2008 R2,Soft Delete,我们应该为软删除使用标志,还是使用单独的joiner表?哪个更有效?数据库是SQL Server 背景信息 不久前,我们有一位数据库顾问进来查看我们的数据库模式。当我们软删除一条记录时,我们会在相应的表上更新IsDeleted标志。有人建议,不要使用标志,而是将删除的记录存储在单独的表中,并使用联接,因为这样会更好。我已经对这个建议进行了测试,但至少从表面上看,额外的表和连接看起来比使用标志更昂贵 初始测试 我已经准备好了这个测试 两个表,Example和DeletedExample。我在IsD

我们应该为软删除使用标志,还是使用单独的joiner表?哪个更有效?数据库是SQL Server

背景信息

不久前,我们有一位数据库顾问进来查看我们的数据库模式。当我们软删除一条记录时,我们会在相应的表上更新IsDeleted标志。有人建议,不要使用标志,而是将删除的记录存储在单独的表中,并使用联接,因为这样会更好。我已经对这个建议进行了测试,但至少从表面上看,额外的表和连接看起来比使用标志更昂贵

初始测试

我已经准备好了这个测试

两个表,Example和DeletedExample。我在IsDeleted列上添加了一个非聚集索引

我做了三次测试,加载了一百万条记录,删除/未删除比率如下:

  • 已删除/未删除
  • 50/50
  • 10/90
  • 1/99
结果-50/50

结果-10/90

结果-1/99

数据库脚本,例如,用于参考、删除示例和索引。IsDeleted

CREATE TABLE [dbo].[Example](
    [ID] [int] NOT NULL,
    [Column1] [nvarchar](50) NULL,
    [IsDeleted] [bit] NOT NULL,
 CONSTRAINT [PK_Example] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Example] ADD  CONSTRAINT [DF_Example_IsDeleted]  DEFAULT ((0)) FOR [IsDeleted]
GO

CREATE TABLE [dbo].[DeletedExample](
    [ID] [int] NOT NULL,
 CONSTRAINT [PK_DeletedExample] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[DeletedExample]  WITH CHECK ADD  CONSTRAINT [FK_DeletedExample_Example] FOREIGN KEY([ID])
REFERENCES [dbo].[Example] ([ID])
GO

ALTER TABLE [dbo].[DeletedExample] CHECK CONSTRAINT [FK_DeletedExample_Example]
GO

CREATE NONCLUSTERED INDEX [IX_IsDeleted] ON [dbo].[Example] 
(
    [IsDeleted] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

我不是SQL专家,但在我看来,这完全取决于数据库的使用频率。如果数据库被大量用户访问并且需要高效,那么使用一个单独的isDeleted表将是很好的。更好的选择是在生产期间使用标志,作为每日/每周/每月维护的一部分,您可以将所有软删除记录移动到isDeleted表中,并清除生产表中的软删除记录。这两个选项的混合将是一个很好的选择。

您的数字似乎表明这是正确的:如果您对该数据库最常见的查询是在
IsDeleted=0
上进行筛选,那么使用简单的位标志将提高性能,特别是如果您明智地使用索引


如果您经常分别查询已删除和未删除的数据,那么您可以看到一个用于已删除项的表和另一个用于未删除项的表,以及相同的字段,从而提高了性能。但是,像这样对数据进行非规范化很少是一个好主意,因为这通常会使您在代码维护方面的成本远远高于在性能提高方面的成本。

这是一个很好的答案。还考虑使用筛选索引。如果在未删除记录时仅按列1查询示例表,请索引列1“WHERE IsDelete=0”。