如果您能帮助我,我会很高兴: 得到一个查询,该查询应该从数据库(Postgres)分区表(由execute_ts分区)中获取一些任务,并让它们以线程安全的方式工作(服务中的多个工作人员同时承担数据库的任务)
UPDATE tasks
SET status = 'IN_WORK'
WHERE execute_ts BETWEEN (now() - INTERVAL '2 day') AND now()
AND id IN (
SELECT id
FROM tasks
WHERE status IN ('INITIAL', 'TO_BE_RETRIED')
AND execute_ts BETWEEN (now() - INTERVAL '2 day') AND now()
LIMIT 1000
FOR UPDATE SKIP LOCKED
)
RETURNING *;
有没有办法避免重复
execute_ts BETWEEN (now() - INTERVAL '2 day') AND now()
条件,因为否则它会遍历所有分区。
尝试使用
CTE
,如下所示
WITH filtered_tasks AS (
SELECT id
FROM tasks
WHERE status IN ('INITIAL', 'TO_BE_RETRIED')
AND execute_ts BETWEEN (now() - INTERVAL '2 day') AND now()
LIMIT 1000
FOR UPDATE SKIP LOCKED
)
UPDATE tasks
SET status = 'IN_WORK'
FROM filtered_tasks
WHERE tasks.id = filtered_tasks.id
RETURNING tasks.*;
ctid
是实现高效自连接的好方法。然而,根据 DBA.SE 上的这个问题,需要将其与 tableoid
结合起来才能在分区表中正常工作,并且应该使用 CTE 而不是子查询:
WITH work AS (
SELECT tableoid, ctid
FROM tasks
WHERE status IN ('INITIAL', 'TO_BE_RETRIED')
AND execute_ts BETWEEN (now() - INTERVAL '2 day') AND now()
LIMIT 1000
FOR UPDATE SKIP LOCKED
)
UPDATE tasks
SET status = 'IN_WORK'
WHERE (tableoid, ctid) IN (TABLE work)
RETURNING *;