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
。
我需要用 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
。