数据库同步和软删除方案中的逻辑删除表与已删除标志


17

我需要跟踪已删除项目,以满足客户端同步的需要。

通常,最好是添加一个逻辑删除表和一个触发器,以跟踪何时从服务器数据库中删除了行-基本上是将逻辑删除表中的数据添加到逻辑删除表中的新行-还是将这些条目保留在原始表并将其标记为已删除(通常使用bit类型的列)以指示已删除行,而另一列用于跟踪删除发生的时间?

Answers:


17

通常,最好了解特定要求,而不是根据在大多数情况下最有效的方法来做出设计决策。 两者都可能更可取。以下是一些要收集的细节:

  • 删除需要多快?
  • 取消删除需要多长时间?
  • 多久查询一次已删除的数据,并与未删除的数据一起查询?
  • 查询删除的数据需要多快?
  • 您是否还需要仅保留已删除的项目或更改?
  • 您是否需要使主表上的表/索引保持较小?
  • 数据库平台上可以使用哪些分区和/或更改跟踪技术?
  • 有多少磁盘空间可用?
  • 删除是在进行中还是在批量操作中进行?

我知道,这是在不同系统需求之间进行权衡的问题。如果我需要快速删除/取消删除,则最好使用该标志,但是如果我需要对已删除项目以及主表进行快速查询,并且可能需要跟踪任何类型的更改,则墓碑方法可能是更好。
洛伦佐·波利多里

你说对了。甚至在某些情况下,最好使用其他选择。例如,如果仅需要24小时就可以使用软删除,则在Oracle中,您可以考虑设置有保证的撤消保留时间,然后使用闪回查询查看已删除的数据。
Leigh Riffel 2012年

5

也许您应该故意将这两种方法结合起来。为什么???

让我们使用该表(MySQL方言)

CREATE TABLE mydata
(
    id int not null auto_increment
    firstname varchar(16) not null,
    lastname varchar(16) not null,
    zipcode char(5) not null,
    ...
    deleted tinyint not null default 0
    KEY (deleted,id),
    KEY (deleted,lastname,firstname,id),
    KEY (deleted,zipcode,id),
    KEY (lastname,firstname),
    KEY (zipcode),
    PRIMARY KEY (id)
);

请注意,除PRIMARY KEY外,您创建的每个索引都应在deleted标志之前,并以末尾id

让我们创建一个墓碑表

CREATE TABLE mytomb SELECT id FROM mydata WHERE 1=2;
ALTER TABLE mytomb ADD PRIMARY KEY (id);

如果您的表已经有一个deleted标记,则可以填充墓碑表

INSERT INTO mytomb SELECT id FROM mydata WHERE deleted = 1;

确定,现在就准备好数据和逻辑删除了。您如何执行删除?

假设您要删除07305邮政编码中的每个人。您将运行以下命令:

INSERT IGNORE INTO mytomb SELECT id FROM mydata WHERE deleted=0 AND zipcode='07305';
UPDATE mydata SET deleted=1 WHERE deleted=0 AND zipcode='07305';

好的,无论从哪种角度看,这似乎都需要很多开销。

现在,您要查看所有已删除的数据吗?这是两种不同的方式:

  • SELECT * FROM mydata WHERE deleted=1;
  • SELECT B.* FROM mytomb A INNER JOIN mydata B USING (id);

如果mytomb中的id数大于mydata的行数的5%,则为全表扫描。否则,进行索引扫描,并为每行进行查找。注意这些方面的任何基准。查找说明计划。

现在,您是否想看到邮政编码为07304的每个人?这是两种不同的方式:

  • SELECT * FROM mydata WHERE deleted=1 AND zipcode='07304';
  • SELECT A.* FROM mydata A LEFT JOIN mytomb B USING (id) WHERE B.id IS NULL AND A.zipcode='07304'

批量删除怎么样?这是两种不同的方式:

  • DELETE FROM mydata WHERE deleted=1;
  • DELETE B.* FROM mytomb A INNER JOIN mydata B USING (id); DELETE FROM mytomb;

结论

现在,我并不是说要保留这两种方法。随着时间的推移,这样做可以揭示哪种方法在整体可操作性方面更快。您必须确定用于查询实时数据,查询已删除数据和批量删除的最佳基准最适合您。


持续使用这两种技术是否有优势?还是建议仅并行使用它们来评估性能,然后承诺其中一项?
所有行业的乔恩2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.