在 PostgreSQL 中,我必须小批量获取 id 并同时删除它们,这样就不会有 2 个客户端获取相同的 id。
遗憾的是 DELETE 不支持 LIMIT,所以我来到的查询 - 如下:
DELETE FROM codes WHERE id in (
SELECT id FROM codes WHERE product = 'abc' LIMIT 100 FOR UPDATE
) RETURNING id
可悲的是,这是一种缓慢且串行的算法(在某些情况下) - 您无法在 DELETE 运行时进行 SELECT,也不能选择相同的 id 两次。在获得 SELECT 结果之前,您无法删除。
当许多客户端并行出现时,这会导致性能不佳。并行化/加速这一切的最佳选择是什么?
PS:当产品与不同的客户端不同时 - 数据库可以很好地并行化它,但是当它们相同时 - 响应时间开始随着并行客户端请求的数量线性增长
使用
SKIP LOCKED
允许并行化。
此外,请在 CTE 中具体化您的选择,因为
LIMIT
子句与锁定子句不能很好地交互。参见:
WITH sel AS (
SELECT id
FROM codes
WHERE product = 'abc'
LIMIT 100
FOR UPDATE SKIP LOCKED
)
DELETE FROM codes s
USING sel s
WHERE c.id = s.id
RETURNING id;
为确保所有行均已处理,请在您认为完成后进行检查。喜欢:
SELECT EXISTS (SELECT FROM codes);
如果仍有剩余行,请运行不带
SKIP LOCKED
的最终命令。
循环最后两个步骤,确保万无一失。