Joh*_*hir 5 postgresql index null alter-table locking
(前一个问题是:将多个列设置为非空时,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)
另一个 postgresql 贡献者的另一个答案。
在执行“alter table set not null”期间,PostgreSQL 甚至不会尝试使用任何索引。它只是没有实施。
正确实施索引扫描是困难的部分。我们不能只做这样的查询
select exists(select from foos where bar1 is null)
Run Code Online (Sandbox Code Playgroud)
由于各种原因,来自 alter table 命令。此类功能将需要大量代码(并且可能在某些边缘情况下需要脆弱的代码)、大量工作,仅适用于有限的用例。开发人员不喜欢的东西。实际上,pgsql-hackers 社区不喜欢 NOT NULL 存储在系统目录中的方式。重新设计目录的这一部分会更清晰。之后,可以使用短锁执行 SET NOT NULL NOT VALID 和没有排他锁的表验证。类似于alter table .. add constraint ... not valid
+alter table .. validate constraint
用于检查约束或外键。但是这样的重新设计工作量很大,而且没有人愿意去做。
但我有个好消息:在 PostgreSQL 12(及更高版本)中,扫描整个表并不是唯一的选择。alter table set not null
可以通过现有的检查约束证明 NOT NULL 的正确性。所以,你可以这样做:
-- short-time exclusive lock
alter table foos
add constraint foos_not_null
check (bar1 is not null) not valid;
-- seqscan, but without exclusive lock, concurrent sessions can read/write
alter table foos validate constraint foos_not_null;
-- exclusive lock, but foos_not_null proves: there is no NULL in this column
-- so this alter table would be fast
alter table foos alter column bar1 set not null;
-- not needed anymore
alter table foos drop constraint foos_not_null;
Run Code Online (Sandbox Code Playgroud)
那是我的补丁。是的,这看起来像是一种解决方法。但是,幸运的是,它被合并了,现在可以set not null
不用长时间的排他锁了。
归档时间: |
|
查看次数: |
928 次 |
最近记录: |