我是Postgres的新手,并且有一个任务要从未分区创建的活动表中删除记录。现在我的头是要创建一个游标以受控方式删除记录。
我头脑中的步骤
这有意义吗?
答案 0 :(得分:0)
DELETE
。忘记光标。
除非表很大并且您要删除很大比例的行,否则分批处理是没有意义的。即使到那时,也几乎没有任何意义。我能想到的唯一原因是允许VACUUM
尽早删除死元组,这在特殊情况下可能会有所帮助。还是为了逃避锁定争用(可能的死锁?),但这引出了一个问题,即为什么要删除的行首先应该由并发事务锁定。
为此锁每行。与并发的INSERT
或UPDATE
至不同行没有冲突。 (如果您有针对某些相同行的UPDATE,则会遇到更大的问题。)无论如何,在Postgres上都是writers don't block readers。
您可以创建一个SQL cursor with the WITH HOLD
option,然后在单独的事务中将其与DELETE ... WHERE CURRENT OF
一起使用。但是您必须抛出FOR UPDATE
,无论如何都锁定所有受影响的行。几乎没有道理,除非您想快速锁定所有受影响的行,但在删除之前仍要对它们进行某些操作,并且可能会有更聪明的方法...
有意义的是,将大UPDATE
分区(在单独的事务中),以便死掉的元组可以在H.O.T.中重用。更新(手动VACUUM
或自动真空启动后)。但这几乎不适用于不重用空间的DELETE
操作。另外,DELETE
比UPDATE
快得多。
在不太可能发生的情况中,您仍然需要分批执行操作,但仍不要使用光标。使用类似的东西:
WITH cte AS (
SELECT id -- your PK
FROM tbl
WHERE date < $something -- your condition
LIMIT 50000
FOR UPDATE -- SKIP LOCKED ?
)
DELETE FROM tbl
USING cte
WHERE tbl.id = cte.id;
重复直到找不到行。
请参阅: