9

我有一个庞大的数据库......不是一个很大的数据库 - 总共大约 1gb 的数据。

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

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

现在我想删除所有有status=1

我想我这样做:

从订单中删除状态=1

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

当我尝试通过使用限制范围时

从订单中删除状态=1且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)

没有任何类型的触发器或规则。更重要的是,我没有添加这是表的新副本,我的意思是它是通过导出/导入从其他服务器移动的。也许这在某种程度上起到了作用?

删除索引会有帮助吗?

4

2 回答 2

10

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

删除作为事务发生,这意味着要么删除所有内容,要么什么都不删除。为确保发生这种情况,需要先将行复制到某处,然后再删除它们。这意味着删除 250k 行所花费的时间与插入那么多行所花费的时间差不多。在某些情况下,创建一个未删除所有内容的新表并将新表重命名为旧表会更快。

如果这是从另一个数据库中移出的,那么如果您可以防止首先插入 250k 行,您可能会更好。

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

于 2011-10-24T18:06:09.543 回答
3

在大桌子上使用 COPY FROM / TURNCATE /COPY TO 要快得多。

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

于 2015-04-24T11:14:18.397 回答