Postgres 9超慢速简单删除

时间:2011-10-24 08:59:29

标签: sql postgresql database-administration

我有一个实质性的数据库......不是很大的数据库 - 总共大约1GB的数据。

我需要从几个表中删除一些行。例如,我有一个表

 Order
 id     | ... | status   | ...
 1      | ... | 1        | ...
 ...
 40     | ... | 20       | ...
 41     | ... | 1        | ...
 ...
 470000 | ... | 12       | ...

现在我要删除所有包含status=1

的订单

我认为我这样做:

  

DELETE FROM Order WHERE status = 1

看起来很简单,但需要很长时间!当我运行此查询时,它仍然在40分钟后以100%CPU使用率运行...当我杀死进程时没有删除任何内容。

当我尝试使用

限制范围时
  

DELETE FROM Order WHERE status = 1 AND id< 1000

删除大约200行需要几分钟....

我的配置中是否有任何遗漏?我应该寻找/检查/改变什么?任何想法都是为什么它如此血腥低效?

让我补充一点,我通常使用MySQL并且需要管理这个postgres数据库,但是对postgres没有任何经验,所以它可能非常简单。

索引在id和status列上。

表有大约500k行,大约一半需要删除。

执行计划:

Delete  (cost=0.00..19474.19 rows=266518 width=6)
->  Seq Scan on Orders  (cost=0.00..19474.19 rows=266518 width=6)
Filter: (statusid = 1)

没有任何触发器或规则。更重要的是,我没有添加这是表的新副本,我的意思是它是从其他服务器移出导出/导入。也许这会以某种方式发挥作用?

删除索引会有帮助吗?

2 个答案:

答案 0 :(得分:8)

在您杀死进程后没有删除任何内容是您应该看到的内容。

删除发生在一个事务中,这意味着要么删除所有内容,要么删除任何内容。为了确保可以发生这种情况,需要在删除行之前将行复制到某处。这意味着删除250k行所需的时间与插入多行相同。在某些情况下,创建一个包含未删除的所有内容的新表会更快,并将新表重命名为旧表。

如果从另一个数据库移动它,如果你可以首先插入250k行,你可能会更好。

(这是一般的RDBMS智慧,而不是特定于postgresql - 有关postgres MVCC如何工作的详细信息可能会有很大差异。)

答案 1 :(得分:2)

在大桌子上使用COPY FROM / TURNCATE / COPY TO会更快。

但是,当然,你必须小心引用,如果可能的话,禁用触发器。