【问题标题】:Postgres 9 super slow simple deletePostgres 9 超慢简单删除
【发布时间】:2011-12-13 23:13:18
【问题描述】:

我有一个庞大的数据库......不是一个很大的数据库 - 总共大约 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

删除大约 200 行花了几分钟....

我的配置中有什么遗漏吗?我应该寻找/检查/更改什么?有什么想法为什么它如此低效?

我补充一下,我通常使用 MySQL,需要管理这个 postgres 数据库,但对 postgres 没有任何经验,所以可能很简单。

索引位于 id 列和状态列上。

表有大约 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)

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

删除索引会有帮助吗?

【问题讨论】:

  • status 列上有索引吗?删除语句的执行计划是怎样的?
  • 通过运行“EXPLAIN”命令:postgresql.org/docs/current/static/sql-explain.html
  • 表格有多少行?那些状态怎么可能= 1?无论如何删除 266518 行不应该花费 40 分钟...
  • 1) 表上是否定义了任何触发器(或规则)? 2)您可以删除所有索引并在之后重新创建它们(您不需要删除索引,删除一半表将导致顺序表扫描。
  • 如果您发布了表定义,并且如果有其他表具有任何引用此表的 FOREIGN KEY 并定义了 ON DELETE 操作,那就太好了。

标签: sql postgresql database-administration


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

    如果这是从另一个数据库中移出的,如果你能防止 250k 行一开始就被插入,你可能会更好。

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

    【讨论】:

    • 嗨,这正是我开始怀疑的......我可以在删除期间切换事务吗?毕竟我不在乎它是否在发生某些事情之前只删除 100k,因为我总是可以再次运行 delete。
    • 如何使用某种增量方法(伪代码): for (my_id = 0; my_id
    猜你喜欢
    • 2017-07-30
    • 2011-10-15
    • 1970-01-01
    • 2020-03-25
    • 1970-01-01
    • 2022-12-03
    • 2019-04-09
    • 2010-09-27
    • 1970-01-01
    相关资源
    最近更新 更多