我需要跟踪已删除项目,以满足客户端同步的需要。
通常,最好是添加一个逻辑删除表和一个触发器,以跟踪何时从服务器数据库中删除了行-基本上是将逻辑删除表中的数据添加到逻辑删除表中的新行-还是将这些条目保留在原始表并将其标记为已删除(通常使用bit类型的列)以指示已删除行,而另一列用于跟踪删除发生的时间?
我需要跟踪已删除项目,以满足客户端同步的需要。
通常,最好是添加一个逻辑删除表和一个触发器,以跟踪何时从服务器数据库中删除了行-基本上是将逻辑删除表中的数据添加到逻辑删除表中的新行-还是将这些条目保留在原始表并将其标记为已删除(通常使用bit类型的列)以指示已删除行,而另一列用于跟踪删除发生的时间?
Answers:
通常,最好了解特定要求,而不是根据在大多数情况下最有效的方法来做出设计决策。 两者都可能更可取。以下是一些要收集的细节:
也许您应该故意将这两种方法结合起来。为什么???
让我们使用该表(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;
现在,我并不是说要保留这两种方法。随着时间的推移,这样做可以揭示哪种方法在整体可操作性方面更快。您必须确定用于查询实时数据,查询已删除数据和批量删除的最佳基准最适合您。