(A pergunta anterior era: o Postgres usará um índice de várias colunas ao definir várias colunas não nulas?)
Normalmente, quando defino uma coluna como não nula, se ela não tiver um índice, eu a adiciono primeiro, para que o postgres possa (espero) usar o índice enquanto faz a varredura da tabela enquanto bloqueia a tabela, para que a tabela seja bloqueada por um menor período de tempo.
Eu quero definir várias colunas não nulas, assim:
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;
Se eu fizer um índice de várias colunas para essas colunas, o postgres o usará ao verificar a tabela bloqueada antes de fazer essa alteração?
CREATE INDEX CONCURRENTLY my_index on foos (bar1, bar2, bar3, bar4);
E se eu fizer um índice parcial em IS NULL (ou 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;
Outra resposta de outro colaborador do postgresql.
O PostgreSQL nem tentará usar nenhum índice durante a execução de "alter table set not null". Simplesmente não é implementado.
A implementação adequada da verificação de índice é uma parte difícil. Não podemos simplesmente fazer algo como esta consulta
do comando alter table por várias razões . Esse recurso exigirá um grande pedaço de código (e, provavelmente, código frágil em alguns casos extremos), muito trabalho, apenas para casos de uso limitados. Algo que os desenvolvedores não gostam. Na verdade, a comunidade pgsql-hackers não gosta de como NOT NULL é armazenado no catálogo do sistema. Ficaria mais limpo com um redesenho desta parte do catálogo. Depois disso, seria possível fazer SET NOT NULL NOT VALID com um bloqueio curto e validação de tabela sem um bloqueio exclusivo. Semelhante a
alter table .. add constraint ... not valid
+alter table .. validate constraint
para restrição de verificação ou chave estrangeira. Mas esse redesenho é muito mais trabalhoso, e não há quem queira fazê-lo.Mas tenho uma boa notícia: no PostgreSQL 12 (e acima) escanear a tabela inteira não é a única opção.
alter table set not null
pode provar a correção de NOT NULL por restrições de verificação existentes. Assim, pode-se fazer:Esse foi o meu patch . Sim, isso parece uma solução alternativa. Mas, felizmente, ele foi mesclado e agora é possível
set not null
sem um longo bloqueio exclusivo.Observei o código-fonte (função
ATRewriteTable
emsrc/backend/commands/tablecmds.c
), e o PostgreSQL sempre usa uma varredura sequencial da tabela para verificar asNOT NULL
restrições.Portanto, criar índices não acelerará a execução.