2013-01-16 61 views
3

假设我有一个包含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.

哪一个更快,为什么?另外,如果有更快的方法删除不能删除的记录,请告诉我。

+1

最快可能会是你想要的记录复制到一个临时表,截断表,然后插入一条记录后面 –

+0

除非查询优化器总废话(这是非常不可能的),三是一样的。 – Damon

+0

这取决于。如果id是(主键)(或索引字段),则三个查询将具有可比较的性能。否则:任何事情都会发生,取决于id域的索引和基数。 – wildplasser

回答

5

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

  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命名约定临时表,但是这是想法。

+0

+1击败我吧 –

+2

虽然这很快,但它使用DDL语句而不是DML语句来实现,如果您不得不关注表间依赖关系,这可能是灾难性的。如果你希望更安全的数据一致性,我希望在'id'(如果它不存在的话)上添加索引并执行'delete';因为要运行删除操作,首先需要选择记录(因此索引可以加速部分操作)。但是,如果原始速度是您唯一关心的问题,那么这可能是最快的方法。 –

+0

截断几乎总是优于删除和重新创建表格。如果有外键等等呢?截断简单得多,并且与删除和重新创建表格一样快。 (如果不是更快) –

6

只要那些影响相同的记录,那些将有相似的性能。

前者使用索引搜索而不是更有效的全表扫描有一点小概率,但它可以忽略不计。

+0

感谢您的伟大答案。不过,我会接受@GordonLinoff答案,因为它提供了一种不同的技术来删除记录。 – MurifoX

3

如果您不能将ID移动到新表中,您可能需要尝试按组或批次删除。有时与一大块记录交易不是最快的。包括任何数据库oracle和微软数据库产品都是这种情况。

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 
+0

很高兴知道。 – MurifoX