(前一个问题是:将多个列设置为非空时,Postgres 会使用多列索引吗?)
通常,当我将列设置为非空时,如果它没有索引,那么我首先添加它,以便 postgres 可以(希望)在锁定表的同时进行表扫描时使用索引,以便表被锁定在较短的时间内。
我想设置几列不为空,如下所示:
alter table foos
alter column bar1 set not null
alter column bar2 set not null
alter column bar3 set not null
alter column bar4 set not null;
Run Code Online (Sandbox Code Playgroud)
如果我为这些列创建了多列索引,那么在进行此更改之前,postgres 会在扫描锁定表时使用它吗?
CREATE INDEX CONCURRENTLY my_index on foos (bar1, bar2, bar3, bar4);
Run Code Online (Sandbox Code Playgroud)
如果我在 IS NULL(或 IS NOT NULL)上建立了部分索引怎么办
CREATE INDEX CONCURRENTLY my_index on foos (bar1, bar2, bar3, bar4) where bar1 is null and bar2 is null and bar3 is null and bar4 is null;
Run Code Online (Sandbox Code Playgroud) 我知道并发创建索引时,只需要一个SHARE ShareUpdateExclusiveLock 锁。
但是,在进程一开始的一小段时间内是否需要更严格类型的锁定?或者整个操作只需要一个SHARE ShareUpdateExclusiveLock 锁?
我这么问是因为我想知道在同时创建索引时设置什么类型的超时是有利的。
我有一个代表时间范围的表格。
Column | Type | Modifiers
-------------+-----------------------------+--------------------------------------------------------------------------
id | bigint | not null default nextval('exploded_recurring_sessions_id_seq'::regclass)
schedule_id | bigint |
start_time | time without time zone |
end_time | time without time zone |
Run Code Online (Sandbox Code Playgroud)
然后我会做一个这样的查询:
select from my_table where localtime >= start_time and localtime < end_time;
Run Code Online (Sandbox Code Playgroud)
在 end_time 是午夜的情况下,这里的业务逻辑是有意义的,因为我认为一个范围包含 start_time 而不包含 end_time。
当然,这个查询实际上不起作用,因为当 end_time 为 00:00:00 时,localtime 永远不会< end_time。
我能想到的有两种解决方案。
00:00:00
,'00:00:00'::time without time zone - interval '1 microsecond'
用于午夜。这一切导致计算错误的可能性可能很低,永远不会发生。即使它每年确实发生几次,其后果基本上不存在,至少在我的系统现在如此。然而,这是一个丑陋的解决方案,使用这样的错误数据可能会产生其他后果。select from my_table where localtime >= start_time and (localtime …
我想做这样的事情:
begin;
select * from foos where owner_id=123 and unread=true order by id for update;
update foos set unread=false where owner_id=123 and unread=true;
commit;
Run Code Online (Sandbox Code Playgroud)
目标是避免两个进程同时执行 UPDATE 时出现死锁。此处详细描述了问题:Why am I get a deadlock for a single UPDATE query?
在我获取锁的语句中,我不需要有关行的任何信息。我只想锁定那些特定的行。有没有办法做到这一点(优雅或hacky),告诉postgres不要做任何实际给我数据的工作?
我有两个进程并行执行这样的代码:
begin;
update foos set unread=false where owner_id=123 and unread=true;
commit;
Run Code Online (Sandbox Code Playgroud)
这会导致死锁。
我对导致死锁的原因的理解就像这个问题中描述的场景,“交织” UPDATE 语句以不同的顺序更新两个不同的行。我不明白单个 UPDATE 语句如何导致死锁。我无法在我的开发环境中使用两个并行 psql 会话来复制死锁场景。我为什么不能复制它的猜测:
这个单一的 UPDATE 是否有可能造成死锁?
我向这样的某些列添加了 NOT NULL 约束,希望命令非常快,因为NOT VALID
. 但是,大约需要 60-100 秒,并且似乎一直锁定表(基于在此期间失败的其他事情)。这是在一个大约有 8,600,000 行的表上。为什么会这样?执行 4 个命令而不是 1 个命令会更好吗?
Postgres 12
ALTER TABLE my_table
ADD CONSTRAINT my_table_column1_not_null CHECK (column1 IS NOT NULL) NOT VALID,
ADD CONSTRAINT my_table_column2_not_null CHECK (column2 IS NOT NULL) NOT VALID,
ADD CONSTRAINT my_table_column3_not_null CHECK (column3 IS NOT NULL) NOT VALID,
ADD CONSTRAINT my_table_column4_not_null CHECK (column4 IS NOT NULL) NOT VALID;
Run Code Online (Sandbox Code Playgroud) postgresql ×6
locking ×3
alter-table ×2
index ×2
update ×2
concurrency ×1
constraint ×1
datetime ×1
deadlock ×1
null ×1
time ×1
transaction ×1