rue*_*ehr 8 postgresql performance delete concurrency postgresql-performance
我有一个包含数亿行的表,我需要从中删除数据。
现有的索引是最有效的。
但是,我可以使用现有索引通过使用ctid值查找要删除的行:
DELETE FROM calendar_event WHERE ctid IN
(SELECT ctid FROM calendar_event WHERE user_id = 5 LIMIT 100 FOR UPDATE)
Run Code Online (Sandbox Code Playgroud)
ctid在这种情况下依赖 的风险是什么?我最糟糕的情况是删除错误的行。
所采用的ROW SHARE锁FOR UPDATE可防止并发写访问会更改行的物理位置。手册:
这可以防止它们被其他事务锁定、修改或删除,直到当前事务结束。也就是说,其他尝试
UPDATE,DELETE,SELECT FOR UPDATE,SELECT FOR NO KEY UPDATE,SELECT FOR SHARE或SELECT FOR KEY SHARE这些行的事务将被阻塞,直到当前事务结束;
因此ctid,除非您自己更改同一事务中的行,否则在命令(或事务,甚至)期间应该是稳定的。ctid仍然是内部使用的系统列,项目将不提供任何保证。如果您有任何唯一的(组合)列(包括 PK),请使用它而不是ctid.
但是,我会使用 CTE 来实现选择并避免意外结果。
无需ORDER BY您选择任意行进行删除。您不妨添加SKIP LOCKED以最大程度地减少并发事务的锁争用:
WITH cte AS (
SELECT ctid
FROM calendar_event
WHERE user_id = 5
LIMIT 100
FOR UPDATE SKIP LOCKED
)
DELETE FROM calendar_event WHERE ctid IN (TABLE cte);
Run Code Online (Sandbox Code Playgroud)
相关,并解释了这两种考虑:
关于ctid:
| 归档时间: |
|
| 查看次数: |
2842 次 |
| 最近记录: |