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



关于这个话题有一些类似的问题,但它们对我没有真正的帮助。

我想实现一个软删除功能,如StackOverflow,其中的项目不是真正删除,但只是隐藏。我使用的是SQL数据库。这里有3个选项:

  • 添加is_deleted布尔字段

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

    • 优点:有日期
    • 缺点:仍然使我的查询变得混乱。

    对于以上两个

    • 它也会影响性能,因为有所有这些无用的行。它们仍然需要在索引中维护。此外,deleted列上的索引在获取未删除(大多数)行的时候也没有帮助。需要全表扫描。

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

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

    有更好的选择吗?

    我个人的回答是基于您预期用户访问删除数据或"恢复"删除数据的频率。

    如果经常,那么我会使用"Date_Deleted"字段,并在代码中的poco中添加计算的"IsDeleted"。

    如果从来没有(或几乎从来没有),那么历史表或已删除表的好处就很好。

    我个人几乎从不使用已删除的表(并选择isDeleted或date_deleted),因为这对引用完整性有潜在的风险。你有A -> B,你从B数据库中删除记录…由于您的设计选择,现在您必须管理引用完整性。

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

    这是另一种思考……的方法。如果键是字母数字,则可以通过在前面加上唯一的"标记"字符来执行类似的操作。由于被删除的记录都以这个标记开始,因此在索引中它们将被单独删除。

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

    我相信你已经列出了三个最常见的选择。正如你所看到的,每一种都有优点和缺点。就我个人而言,我喜欢从长远的角度看问题。

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

    使用带有删除标志的表:如果你的索引都首先包含已删除的标志字段,并且你的查询大多包含where isdeleted=false类型结构,那么它确实解决了你的性能问题,索引非常有效地排除了已删除的行。类似的逻辑可以用于删除日期选项。

    使用两个表通常,您需要对报表进行大量更改,因为有些报表可能引用已删除的数据(例如旧的销售数字可能引用已删除的销售类别)。可以通过创建一个视图来克服这个问题,该视图是两个表的联合,可以读取并且只写入活动记录表。

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

    最新更新