实现软删除,对性能和代码的影响最小

时间:2011-09-09 20:02:34

标签: sql soft-delete

该主题有一些similar questions,但他们并没有真正帮助我。

我想在StackOverflow上实现一个软删除功能,其中的项目并没有真正删除,只是隐藏了。我正在使用SQL数据库。以下是3个选项:

  • 添加is_deleted布尔字段。

    • 优点:简单。
    • 缺点:没有日期记录。强制我在每个查询中添加is_deleted = 0
  • 添加deleted_date日期字段。如果未删除,则设置为NULL

    • 优点:有约会。
    • 缺点:我的查询仍然混乱。

对于上述两个

  • 它还会影响性能,因为存在所有这些无用的行。它们仍然必须保持在索引中。在获取未删除(大多数)的行时,deleted列上的索引也无济于事。需要全表扫描。

另一种选择是创建一个单独的表来保存已删除的项目:

  • 优点:查询未删除的行时提高了性能。无需在未删除的行上添加查询条件。索引维护更容易。
  • 缺点:复杂性:删除和取消删除都需要数据迁移。需要新表。参照完整性更难处理。

有更好的选择吗?

5 个答案:

答案 0 :(得分:3)

我个人的回答是基于您预计用户希望访问已删除数据或“恢复”已删除数据的频率。

如果经常这样,那么我会使用“Date_Deleted”字段并在代码中将“IsDeleted”计算在我的poco中。

如果它从未(或几乎从不),那么历史表或删除的表格对您解释的好处是有益的。

我个人几乎从不使用已删除的表(并选择isDeleted或date_deleted),因为这可能会导致参考完整性。你有A - > B,你从B数据库中删除记录......由于你的设计选择,你现在必须管理参考完整性。

答案 1 :(得分:2)

在我看来,在考虑扩展和最终的表/数据库大小时,最好的方法是第三种选择 - 一个单独的表来删除项目。这样的表最终可以移动到不同的数据库以支持扩展。

我相信你列出了三个最常见的选项。如您所见,每个都有优点和缺点。就个人而言,我喜欢对事物采取更长远的观点。

答案 2 :(得分:2)

如果密钥是数字,我通过否定密钥来处理“软删除”。 (当然,不适用于身份密钥)。您根本不需要更改代码,并且可以通过乘以-1轻松恢复记录。

另一种方法可以考虑......如果密钥是字母数字,你可以通过添加一个独特的“标记”字符来做类似的事情。由于删除的记录都将以此标记开头,因此将在索引中自行结束。

答案 3 :(得分:1)

假设我们创建一个名为dead的字段来标记已删除的行。我们可以创建一个索引,其中字段dead为false。 这样,我们只使用提示使用索引搜索未删除的行。

答案 4 :(得分:1)

我认为您对选项的分析很好,但您错过了我在下面列出的几个相关点。几乎我所见过的所有实现都使用了你在前两个选项中建议的行上的某种删除或版本控制字段。

使用一个已删除标记的表格 如果索引首先包含已删除的标志字段,并且您的查询主要包含where isdeleted = false类型结构,那么它可以解决您的性能问题,并且索引可以非常有效地排除已删除的行。类似的逻辑可用于删除日期选项。

使用两个表 通常,您需要对报告进行大量更改,因为某些报告可能会引用已删除的数据(例如旧的销售数据可能会引用已删除的销售类别)。可以通过创建一个视图来解决这个问题,该视图是两个表的并集,用于读取和仅写入活动记录表。