5

假设我有一个包含 200k+ 行的表的数据库。
该表有一个 id 为 1800 的固定元组。元组序列的其余部分从 300k+ 开始。
我需要清理这张表,删除所有记录而不删除 id 为 1800 的一个寄存器。我想出了 3 种类型的查询,我可以运行:

DELETE FROM table WHERE id > 1800
DELETE FROM table WHERE id <> 1800
DELETE FROM table WHERE id NOT IN (1800)

我感觉第一个比其他更快,但我不确定,因为所有其他数据的 id 都大于 1800。

其中哪一个更快,为什么?另外,如果有一种更快的方法可以删除除无法删除的记录之外的记录,请告诉我。

4

4 回答 4

9

大多数数据库中最快的方法是:

  1. 将id为1800的记录选择到临时表中
  2. 删除原始表
  3. 将临时表中的数据复制到全表中

诚然,由于触发器、约束和权限,这可能是不可能的。在许多数据库中,您可以通过修改 (2) 来截断表而不是删除它来做类似的事情。

至于您最初的问题,实际删除行和与之关联的数据的开销将主导查询。你如何进行比较无关紧要。

示例代码

create temp table saved as
    select * from t where id = 1800

truncate table t

insert into t
    select * from saved

我不确定临时表的 Postgres 命名约定,但这就是想法。

于 2013-01-16T19:24:58.103 回答
6

只要它们影响相同的记录,它们就会具有相似的性能。

前者使用索引搜索而不是更有效的全表扫描的可能性很小,但可以忽略不计。

于 2013-01-16T19:25:27.983 回答
3

如果您无法将 ID 移动到新表中,您可能需要尝试分组或批量删除。有时,处理包含大量记录的事务不是最快的。包含的任何数据库 oracle 和 microsoft 数据库产品都是这种情况。

BEGIN TRANSACTION;
DELETE FROM table WHERE id >= 0 and  id < 20000 and id != 1800;
COMMIT TRANSACTION;
BEGIN TRANSACTION;
DELETE FROM table WHERE id >= 20000 and  id < 40000 and id != 1800;
COMMIT TRANSACTION;
etc
etc
于 2013-01-16T19:36:22.433 回答
1

如果您只想保存最后一条记录并删除所有其他记录,您可以使用以下对我有用的查询

delete from public.table_name
WHERE lastrun_ts < (
   select MAX(lastrun_ts)
   FROM public.table_name
   ORDER BY MAX(lastrun_ts) DESC
   );
于 2019-05-02T19:20:12.903 回答