我有一个实质性的数据库......不是很大的数据库 - 总共大约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)
没有任何触发器或规则。更重要的是,我没有添加这是表的新副本,我的意思是它是从其他服务器移出导出/导入。也许这会以某种方式发挥作用?
删除索引会有帮助吗?
答案 0 :(得分:8)
在您杀死进程后没有删除任何内容是您应该看到的内容。
删除发生在一个事务中,这意味着要么删除所有内容,要么删除任何内容。为了确保可以发生这种情况,需要在删除行之前将行复制到某处。这意味着删除250k行所需的时间与插入多行相同。在某些情况下,创建一个包含未删除的所有内容的新表会更快,并将新表重命名为旧表。
如果从另一个数据库移动它,如果你可以首先插入250k行,你可能会更好。
(这是一般的RDBMS智慧,而不是特定于postgresql - 有关postgres MVCC如何工作的详细信息可能会有很大差异。)
答案 1 :(得分:2)
在大桌子上使用COPY FROM / TURNCATE / COPY TO会更快。
但是,当然,你必须小心引用,如果可能的话,禁用触发器。