使用 IN 语句强制分区修剪并在 Postgres 中选择更新

问题描述 投票:0回答:2

如果您能帮助我,我会很高兴: 得到一个查询,该查询应该从数据库(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()
条件,因为否则它会遍历所有分区。

postgresql partitioning
2个回答
0
投票

尝试使用

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.*;

0
投票

元组标识符

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 *;
© www.soinside.com 2019 - 2024. All rights reserved.