我想在PostgreSQL中对表进行大量更新,但我不需要在整个操作中维护事务完整性,因为我知道我正在更改的列不会被写入或读取更新.我想知道psql控制台中是否有一种简单的方法可以更快地完成这些类型的操作.
例如,假设我有一个名为"orders"的表,有3500万行,我想这样做:
UPDATE orders SET status = null;
Run Code Online (Sandbox Code Playgroud)
为避免被转移到offtopic讨论,让我们假设3500万列的所有状态值当前都设置为相同(非空)值,从而使索引无用.
此语句的问题是需要很长时间才能生效(仅因为锁定),并且所有更改的行都将被锁定,直到整个更新完成.此更新可能需要5个小时,而类似
UPDATE orders SET status = null WHERE (order_id > 0 and order_id < 1000000);
Run Code Online (Sandbox Code Playgroud)
可能需要1分钟.超过3500万行,执行上述操作并将其分成35块只需要35分钟,节省了4小时25分钟.
我可以用脚本进一步分解它(在这里使用伪代码):
for (i = 0 to 3500) {
db_operation ("UPDATE orders SET status = null
WHERE (order_id >" + (i*1000)"
+ " AND order_id <" + ((i+1)*1000) " + ")");
}
Run Code Online (Sandbox Code Playgroud)
此操作可能仅在几分钟内完成,而不是35分钟.
所以这归结为我真正的要求.我不想写一个怪异的脚本来分解操作,每次我想做这样一个大的一次性更新.有没有办法在SQL中完成我想要的东西?
我有Postgresql函数,它必须将大约150万个数据插入表中.我想要的是我希望看到每个记录插入填充表格.目前当我尝试使用大约1000条记录时会发生什么,只有在完成函数执行后才会填充get.如果我在中途停止功能,则不会填充任何数据.即使在插入了一定数量的记录后停止,我怎样才能提交记录?
在PostgreSQL中,是在事务完成之前(之内)还是之后执行的DEFERRED触发器?
该文件说:
DEFERRABLE
NOT DEFERRABLE
这可以控制是否可以延迟约束.在每个命令之后立即检查不可延迟的约束.检查可延迟的约束可以推迟 到事务结束(使用
SET CONSTRAINTS
命令).
它没有指定它是否仍在事务内部或外部.我个人的经验说它在交易中,我需要它在外面!
是DEFERRED
(或INITIALLY DEFERRED
)触发器是在事务内部执行的吗?如果是,我怎么能将他们的执行推迟到交易完成的时间?
为了给你一个提示,我正在使用pg_notify
和RabbitMQ(PostgreSQL LISTEN Exchange)发送消息.我在外部应用程序中处理此类消息.现在我有一个触发器,它通过在消息中包含记录的id来通知外部应用程序新插入的记录.但是,以一种非确定性的方式,偶尔,当我尝试通过其手头的id选择记录时,无法找到记录.那是因为事务尚未完成,并且记录实际上没有添加到表中.如果我只能在事务完成后推迟执行触发器,那么一切都会成功.
为了得到更好的答案,让我更接近现实世界来解释情况.实际情况比我之前解释的要复杂一些.该源代码可以在这里找到,如果任何人的兴趣.由于我不打算深入研究的原因,我必须从另一个数据库发送通知,以便实际发送通知,如:
PERFORM * FROM dblink('hq','SELECT pg_notify(''' || channel || ''', ''' || payload || ''')');
Run Code Online (Sandbox Code Playgroud)
我确信这使得整个情况变得更加复杂.
postgresql notifications triggers transactions deferred-execution
如果存储过程在中间失败,那么从SP开始的那一点的更改是否隐式回滚,或者我们是否必须编写任何显式代码以确保SP仅在数据库事务中运行?
database postgresql stored-procedures transactions relational-database
在 Postgres 12 数据库中,我在一个函数中有多个查询(SELECT
、UPDATE
、 ...),总共需要大约 20 分钟才能完成。我在顶部有一个检查,它执行UPDATE
ifstatus
未运行:
create or replace function aaa.fnc_work() returns varchar as
$body$
begin
if (select count(*) from aaa.monitor where id='invoicing' and status='running')=0 then
return 'running';
else
update aaa.monitor set status='running' where id='invoicing';
end if;
--- rest of code ---
--finally
update aaa.monitor set status='idle' where id='invoicing';
return '';
exception when others then
return SQLERRM::varchar;
end
$body$
language plpgsql;
Run Code Online (Sandbox Code Playgroud)
这个想法是为了防止其他用户执行直到--- rest of code ---
空闲status
。
然而,其他人(调用相同的函数)似乎看不到更新的状态,他们也继续并开始执行 …
postgresql stored-procedures transactions plpgsql task-queue
我想更新 postgres 表的一列。记录大约有 5500 万条,因此我们需要批量更新 10000 条记录。注意:我们要更新所有行。但我们不想锁定我们的桌子。
我正在尝试以下查询 -
Update account set name = Some name where id between 1 and 10000
Run Code Online (Sandbox Code Playgroud)
我们如何为每 10000 条记录更新创建一个循环?
任何建议和帮助将不胜感激。
PostgreSQL 10.5
我有一个需要在多个大表上执行长时间更新的函数.在更新期间,一次需要将2-3个表锁定在EXCLUSIVE模式下.
由于并非所有表都需要同时锁定,理想情况下我只想锁定那些我当时正在更新的表,然后在我完成后删除锁.
例如.
-- Lock first pair of tables
LOCK TABLE tbl1_a IN EXCLUSIVE MODE;
LOCK TABLE tbl1_b IN EXCLUSIVE MODE;
-- Perform the update on tbl1_a and tbl1_b
-- Release the locks on tbl1_a and tbl1_b
-- HOW???
-- Proceed to the next pair of tables
LOCK TABLE tbl2_a IN EXCLUSIVE MODE;
LOCK TABLE tbl2_b IN EXCLUSIVE MODE;
Run Code Online (Sandbox Code Playgroud)
不幸的是,在plpgsql中没有等效的UNLOCK语句.删除LOCK的常规方法是COMMIT事务,但这在函数内部是不可能的.
这有什么解决方案吗?在函数完成之前显式释放锁的某种方法?或者运行某种子事务(也许通过在单独的函数中运行每个更新)?
UPDATE
我接受了没有解决方案.我将每个更新写入一个单独的函数并从数据库外部进行协调.感谢大家.
Postgres 8.4 在这里。想象一下来自 Postgres doc 的这个代码片段:
CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
BEGIN
-- Check that empname and salary are given
IF NEW.empname IS NULL THEN
RAISE EXCEPTION 'empname cannot be null';
END IF;
IF NEW.salary IS NULL THEN
RAISE EXCEPTION '% cannot have null salary', NEW.empname;
END IF;
-- Who works for us when she must pay for it?
IF NEW.salary < 0 THEN
RAISE EXCEPTION '% cannot have a negative salary', NEW.empname;
END IF;
-- …
Run Code Online (Sandbox Code Playgroud) postgresql ×8
plpgsql ×5
transactions ×4
sql ×2
triggers ×2
commit ×1
database ×1
dblink ×1
exception ×1
function ×1
sql-update ×1
task-queue ×1