PostgreSQL 批量更新记录

PostgreSQL Update Records in Batches

我需要用 PostgreSQL 数据库中的大量数据更新 table 中的一列。

由于数据量很大,该作业可能会连续 运行 持续 1 或 2 天,因此我需要分批处理并分批提交事务,以便我可以跟踪进度并打印任何失败的批次的日志,并在稍后通过提供失败的偏移量和限制来手动 运行 它们。

我尝试执行此操作的一种方法是在 postgres 块中使用以下方法,但失败了,因为我无法在 where 子句中使用 row_number()。

DO LANGUAGE plpgsql $$
DECLARE

    row_count_  integer;

    offset_     integer := 0;
    batch_size_ integer := 100000;
    limit_      integer := offset_ + batch_size_;

    total_rows_ integer;

BEGIN

    WHILE offset_ < total_rows_ LOOP
        limit_ := offset_ + batch_size_;
    
        UPDATE table1 
            SET column1 = 'Value' 
            WHERE row_number() over() >= offset_ AND row_number() over() < limit_;
        GET DIAGNOSTICS row_count_ = row_count;
        RAISE INFO '% rows updated from % to %', row_count_, offset_, limit_;
    
        offset_ := offset_ + batch_size_;
    END LOOP;

EXCEPTION WHEN OTHERS THEN 

    RAISE NOTICE 'Transaction is rolling back, % : %', SQLSTATE, SQLERRM;
    ROLLBACK;
   
END $$;

我什至可以使用 python 脚本来执行此操作,但我需要以最快的方式执行此操作。我浏览了很多使用 select 子查询的文章,在我看来,由于加入太昂贵了。

有人可以帮我更好地实现这个目标吗?

如果 activity 持续数天,分批进行 UPDATE 是有意义的。您可能希望 运行 在批次之间的 table 上显式 VACUUM 以避免 table 膨胀。

关于您的核心问题,我认为最简单的解决方案是按主键值进行批处理,即 运行 语句,例如:

UPDATE tab
SET col = newval
WHERE id <= 100000
  AND /* additional criteria*/;

VACUUM tab;

UPDATE tab
SET col = newval
WHERE id > 100000 AND id <= 200000
  AND /* additional criteria*/;

...

不断重复,直到达到最大值 id