实现软删除的最佳方法是什么?

sql database database-design backup

26670 观看

14回复

32339 作者的声誉

目前正在处理项目,我们必须为大多数用户(用户角色)实施软删除。我们决定在数据库中的每个表上添加“is_deleted ='0'”字段,如果特定用户角色点击特定记录上的删除按钮,则将其设置为“1”。

对于将来的维护,每个SELECT查询都需要确保它们不包含is_deleted ='1'的记录。

是否有更好的解决方案来实现软删除?

更新:我还应该注意到,我们有一个Audit数据库,用于跟踪Application数据库中所有表/字段的更改(字段,旧值,新值,时间,用户,ip)。

作者: Josh Smeaton 的来源 发布者: 2008 年 9 月 16 日

回应 (14)


46

2296 作者的声誉

决定

您可以对包含该WHERE IS_DELETED='0'子句的视图执行所有查询。

作者: David J. Sokol 发布者: 16.09.2008 12:49

13

48660 作者的声誉

如果表很大并且性能有问题,您可以随时将“已删除”记录移动到另一个表,其中包含删除时间,删除记录等其他信息。

这样您就不必在主表中添加其他列

作者: Jiaaro 发布者: 16.09.2008 12:49

84

24579 作者的声誉

我倾向于一个deleted_at包含删除发生日期时间的列。然后,您将获得有关删除的一些免费元数据。对于你SELECT刚才获得的行WHERE deleted_at IS NULL

作者: ctcherry 发布者: 16.09.2008 12:50

10

25292 作者的声誉

这取决于您需要哪些信息以及您希望支持哪些工作流程。

你想要能够:

  • 知道那里有什么信息(在删除之前)?
  • 知道什么时候被删除了?
  • 知道谁删了它?
  • 知道他们删除它时的行为能力是什么?
  • 能够取消删除记录吗?
  • 能够告诉它何时被删除?
  • 等等

如果记录被删除和未删除四次,是否足以让您知道它当前处于未删除状态,或者您是否希望能够告知过渡期间发生的事情(包括连续之间的任何编辑)删除!)?

作者: Daniel Fortunov 发布者: 16.09.2008 12:57

4

11773 作者的声誉

如果您将已删除的数据移动到Jim所说的另一个表格中,并且记录删除时间,原因以及由谁删除,您肯定会有更好的表现。

添加到您的所有查询将显着减慢它们的速度,并阻碍您在表上使用的任何索引的使用。尽可能避免在表格中使用“标志”。where deleted=0

作者: Brent 发布者: 16.09.2008 12:57

20

1925 作者的声誉

is_deleted列是一个相当好的方法。如果它在Oracle中,为了进一步提高性能,我建议通过在is_deleted列上创建列表分区来对表进行分区。然后删除和未删除的行将物理上位于不同的分区中,但对于您来说它将是透明的。

因此,如果您键入一个类似的查询

SELECT * FROM table_name WHERE is_deleted = 1

然后Oracle将执行“分区修剪”,只查看相应的分区。在内部,分区是一个不同的表,但作为用户,它对您来说是透明的:无论是否分区,您都可以在整个表中进行选择。但Oracle将只能查询它所需的分区。例如,假设您有1000行is_deleted = 0和100000行is_deleted = 1,并对表进行分区is_deleted。现在,如果你包括条件

WHERE ... AND IS_DELETED=0

那么Oracle将只扫描1000行的分区。如果表未分区,则必须扫描101000行(两个分区)。

作者: Sergey Stadnik 发布者: 16.09.2008 01:01

0

45051 作者的声誉

我更喜欢保留状态列,因此我可以将它用于几种不同的配置,即已发布,私有,已删除,needsAproval ...

作者: UnkwnTech 发布者: 16.09.2008 01:09

0

54538 作者的声誉

使用检查is_deleted = 0的视图,函数或过程,即如果由于其他原因需要稍后更改表,请不要直接在表上选择

并为较大的表索引is_deleted列

由于您已有审计跟踪,因此跟踪删除日期是多余的

作者: Steven A. Lowe 发布者: 16.09.2008 03:25

1

0 作者的声誉

我在项目中使用的东西是statusInd tinyint not null默认0列使用statusInd作为位掩码允许我执行数据管理(删除,存档,复制,恢复等)。在视图中使用它,然后我可以为消费应用程序进行数据分发,发布等。如果性能是关于视图的问题,请使用小事实表来支持此信息,删除事实,删除关系并允许删除删除。

可以很好地扩展并以数据为中心,使数据占用空间非常小 - 对于350gb + dbs而言,实时关注的关键。使用替代方案,表,触发器有一些开销,根据需要可能或可能不适合您。

与SOX相关的审核可能需要不止一个字段来帮助您,但这可能会有所帮助。请享用

作者: Raymond Porrata 发布者: 16.09.2008 05:31

14

6825 作者的声誉

遗憾的是,最好的响应取决于您尝试使用软删除以及您正在实现此功能的数据库。

在SQL Server中,最好的解决方案是使用类型为SMALLDATETIME或DATETIME的deleted_on / deleted_at列(取决于必要的粒度)并使该列可以为空。在SQL Server中,行标题数据包含表中每个列的NULL位掩码,因此执行IS NULL或IS NOT NULL比检查存储在列中的值要快一些。

如果您有大量数据,则需要通过数据库本身或通过两个单独的表(例如Products和ProductHistory)或通过索引视图来查看数据分区。

我通常会避免像is_deleted,is_archive等标志字段,因为它们只带有一个含义。可以为null的deleted_at,archived_at字段为您自己和继承您的应用程序的人提供了额外的意义。我避免像瘟疫这样的位掩码字段,因为它们需要了解如何构建位掩码以便掌握任何含义。

作者: Jeremiah Peschka 发布者: 16.09.2008 12:47

2

2331 作者的声誉

你没有提到什么产品,但SQL Server 2008和postgresql(以及其他我肯定的)允许你创建过滤索引,所以你可以创建一个覆盖索引,其中is_deleted = 0,减轻了这种特殊方法的一些负面影响。

作者: Andy Irving 发布者: 16.09.2008 02:15

7

71 作者的声誉

小心软删除的记录导致违反唯一性约束。如果您的数据库具有唯一约束的列,请注意先前的软删除记录不会阻止您重新创建记录。

想想周期:

  1. 创建用户(login = JOE)
  2. soft-delete(将已删除列设置为非null。)
  3. (重新)创建用户(login = JOE)。错误。已登录LOGIN = JOE

第二次创建导致约束违规,因为login = JOE已经在软删除行中。

一些技巧:1。将删除的记录移动到新表。2.在login和deleted_at timestamp列中创建唯一性约束

我自己的意见是+1移动到新表。它需要很多纪律来维护所有查询中的* AND delete_at = NULL *(适用于所有开发人员)

作者: Andy Rappaport 发布者: 04.05.2011 02:16

0

1 作者的声誉

创建其他模式并将其全部授予您的数据模式。在新模式上实现VPD,以便每个查询都有谓词,允许选择仅附加到其上的未删除行。 http://download.oracle.com/docs/cd/E11882_01/server.112/e16508/cmntopc.htm#CNCPT62345

作者: adsm 发布者: 27.06.2011 11:15

0

3914 作者的声誉

@AdditionalCriteria(“this.status <>'删除'”)

把它放在你的@entity之上

http://wiki.eclipse.org/EclipseLink/Examples/JPA/SoftDelete

作者: Kalpesh Soni 发布者: 21.05.2014 02:26
32x32