我想更新postgres表的一列。记录大约有5500万条,所以我们需要在10000条记录中更新它。注意:我们要更新所有行。但我们不想锁桌子。
我正在尝试以下查询-
Update account set name = Some name where id between 1 and 10000
我们如何为每10000条记录更新做一个循环?
如有任何建议和帮助,将不胜感激。
PostgreSQL 10.5
设置测试环境:
DROP TABLE IF EXISTS account;
CREATE TABLE account(id integer, name text);
INSERT INTO account
VALUES (1, 'jonas'),(10002, 'petras');
更新脚本:
DO $$
DECLARE
_id integer;
_min_id integer;
_max_id integer;
_batch_size integer = 10000;
BEGIN
SELECT
MIN(id),
MAX(id)
INTO
_min_id,
_max_id
FROM
account;
_id := _min_id;
LOOP
UPDATE account SET
name = 'Some name'
WHERE id >=_id
AND id < _id + _batch_size;
COMMIT;
_id := _id + _batch_size;
IF _id > _max_id THEN
EXIT;
END IF;
END LOOP;
END;
$$;
您可以使用一个过程(从版本11开始提供)并逐个执行,如下所示:
CREATE or replace PROCEDURE do_update()
LANGUAGE plpgsql
AS $$
BEGIN
FOR i IN 1..55000000 -- 55 million, or whatever number you need
LOOP
Update account set name = Some name where id = i;
COMMIT;
RAISE INFO 'id: %', i;
END LOOP;
END;
$$;
CALL do_update();
与其一次提交所有更改(或其他答案中建议的5500万次),我宁愿尝试将更新行拆分为小批量,例如,如您建议的10k条记录。在PL/pgSQL中,可以使用关键字BY
以给定步骤迭代集合。因此,您可以在匿名代码块中执行批更新,如下所示:
DO $$
DECLARE
page int := 10000;
min_id bigint; max_id bigint;
BEGIN
SELECT max(id),min(id) INTO max_id,min_id FROM account;
FOR j IN min_id..max_id BY page LOOP
UPDATE account SET name = 'your magic goes here'
WHERE id >= j AND id < j+page;
COMMIT;
END LOOP;
END; $$;
WHERE
子句以避免不必要的重叠。带有顺序id的1051行的数据样本:
CREATE TABLE account (id int, name text);
INSERT INTO account VALUES(generate_series(0,1050),'untouched record..');
正在执行匿名代码块...
DO $$
DECLARE
page int := 100;
min_id bigint; max_id bigint;
BEGIN
SELECT max(id),min(id) INTO max_id,min_id FROM account;
FOR j IN min_id..max_id BY page LOOP
UPDATE account SET name = now() ||' -> UPDATED ' || j || ' to ' || j+page
WHERE id >= j AND id < j+page;
RAISE INFO 'committing data from % to % at %', j,j+page,now();
COMMIT;
END LOOP;
END; $$;
INFO: committing data from 0 to 100 at 2021-04-14 17:35:42.059025+02
INFO: committing data from 100 to 200 at 2021-04-14 17:35:42.070274+02
INFO: committing data from 200 to 300 at 2021-04-14 17:35:42.07806+02
INFO: committing data from 300 to 400 at 2021-04-14 17:35:42.087201+02
INFO: committing data from 400 to 500 at 2021-04-14 17:35:42.096548+02
INFO: committing data from 500 to 600 at 2021-04-14 17:35:42.105876+02
INFO: committing data from 600 to 700 at 2021-04-14 17:35:42.114514+02
INFO: committing data from 700 to 800 at 2021-04-14 17:35:42.121946+02
INFO: committing data from 800 to 900 at 2021-04-14 17:35:42.12897+02
INFO: committing data from 900 to 1000 at 2021-04-14 17:35:42.134388+02
INFO: committing data from 1000 to 1100 at 2021-04-14 17:35:42.13951+02
...您可以批量更新您的行。为了证明我的观点,以下查询按更新时间对记录进行分组:
SELECT DISTINCT ON (name) name, count(id)
FROM account
GROUP BY name ORDER BY name;
name | count
------------------------------------------------------+-------
2021-04-14 17:35:42.059025+02 -> UPDATED 0 to 100 | 100
2021-04-14 17:35:42.070274+02 -> UPDATED 100 to 200 | 100
2021-04-14 17:35:42.07806+02 -> UPDATED 200 to 300 | 100
2021-04-14 17:35:42.087201+02 -> UPDATED 300 to 400 | 100
2021-04-14 17:35:42.096548+02 -> UPDATED 400 to 500 | 100
2021-04-14 17:35:42.105876+02 -> UPDATED 500 to 600 | 100
2021-04-14 17:35:42.114514+02 -> UPDATED 600 to 700 | 100
2021-04-14 17:35:42.121946+02 -> UPDATED 700 to 800 | 100
2021-04-14 17:35:42.12897+02 -> UPDATED 800 to 900 | 100
2021-04-14 17:35:42.134388+02 -> UPDATED 900 to 1000 | 100
2021-04-14 17:35:42.13951+02 -> UPDATED 1000 to 1100 | 51
演示:<代码>数据库
在我的用户表中,我需要在凌晨12点将“每日”列恢复为默认值“1”。 是否有一种方法可以让我在每天上午12点将值恢复为默认值1或将100万条记录的值更新为1,而不延迟任何时间(意味着所有用户的“每日”列将同时更新)? 注:“每日”列用于确定用户是否已“用完”其每日单击。用户每天有1次机会点击按钮(有点像奖励框)。单击按钮后,每日将更新为“0”,直到第二天才能再次单击按钮。
问题内容: 我需要在一个请求中进行多次更新。 在我有: 因此需要进行更改。 这是我的序列化器代码: 我试图添加: 和 但这不起作用。如何更改此代码以进行多次更新。我的json请求 问题答案: 这是您请求的CreateMixins或UpdateMixins的示例。 ======================查看========================== ====== ==========
我有一个目标表(已经填充了数据)和另一个(源表),我需要将数据检索到第一个。 目标_表格 source_table 我需要使用 tusers 表中的 id 更新 ttasks 表id_user列,因此 ttasks 的最终结果应该是: 我尝试过的(类似于INSERT… from…语句): 但是这个查询总是使用我的q1子查询中的第一个id。 关于我如何完成这项任务,有什么想法、帮助甚至解决方案吗?非
我有一个“Customer”表,它有将近120万条记录,其中一列是ntext类型的“customer_records ”,它包含xml数据。我需要在该列的所有现有记录中替换一个url值。我尝试了下面的替换查询,但是执行该查询需要大约20分钟的时间。 在更新期间,CPU 消耗被利用到最大,这引起了问题。在 120 万条记录中,实际更新的记录中有 60 万条记录,但查询需要读取每条记录以查找和替换 U
我有两个结构相同的表,我想使用另一个表的数据更新一个表,匹配主键。SQLite有一个with(CTE)语句,但以下语句不起作用(sqlite3 v.3.29.0): 我尝试过使用“选择main.ID作为ID,选择temp.Desc作为Desc”,但得到了相同的错误消息。
问题内容: 我使用TablePlus(SQL客户端)将Postgres SQL文件导入到服务器,但是在插入新行后出现如下错误: SQLSTATE [23505]:唯一冲突:7错误:重复的键值违反了唯一约束\“ users_pkey \”详细信息:密钥(id)=(1)已存在 我知道它是由序列值0引起的,需要通过以下代码进行更新: 但是,如果我必须一一写入所有表序列(可能是数百个序列),则需要花费大量