Existem alguns mal-entendidos aqui:
O mapa de bits nulo é não parte do cabeçalho montão tuplo. Por documentação:
Há um cabeçalho de tamanho fixo (ocupando 23 bytes na maioria das máquinas), seguido por um bitmap nulo opcional ...
Suas 32 colunas anuláveis não são suspeitas por dois motivos:
O bitmap nulo é adicionado por linha e somente se houver pelo menos um NULL
valor real na linha. As colunas anuláveis não têm impacto direto, apenas os NULL
valores reais . Se o bitmap nulo estiver alocado, ele sempre será alocado completamente (tudo ou nada). O tamanho real do bitmap nulo é de 1 bit por coluna, arredondado para o próximo byte . Por código de fonte atual:
#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
O bitmap nulo é alocado após o cabeçalho da tupla de heap e seguido por um OID opcional e dados da linha. O início de um OID ou dados de linha é indicado por t_hoff
no cabeçalho. Por código fonte do comentário :
Observe que t_hoff deve ser um múltiplo de MAXALIGN.
Há um byte livre após o cabeçalho da tupla de heap, que ocupa 23 bytes. Portanto, o bitmap nulo para linhas de até 8 colunas efetivamente não tem custo adicional. Com a 9ª coluna da tabela, t_hoff
são avançados outros MAXALIGN
bytes (normalmente 8) para fornecer outras 64 colunas. Portanto, a próxima borda teria 72 colunas.
Para exibir informações de controle de um cluster de banco de dados PostgreSQL (incl. MAXALIGN
), Exemplo para uma instalação típica do Postgres 9.3 em uma máquina Debian:
sudo /usr/lib/postgresql/9.3/bin/pg_controldata /var/lib/postgresql/9.3/main
Atualizei as instruções na resposta relacionada que você citou .
Tudo isso à parte, mesmo que sua ALTER TABLE
instrução desencadeie uma reescrita de uma tabela inteira (o que provavelmente ocorre, alterando um tipo de dados), 250K não são muito e seria uma questão de segundos em qualquer máquina decente (a menos que as linhas sejam extraordinariamente grandes) . 10 minutos ou mais indicam um problema completamente diferente. O seu extrato está aguardando um bloqueio na mesa, provavelmente.
O crescente número de entradas pg_stat_activity
significa mais transações abertas - indica acesso simultâneo à tabela (provavelmente) que precisa aguardar a conclusão da operação.
Alguns tiros no escuro
Verifique se há um inchaço na tabela, tente um método VACUUM mytable
mais suave ou mais agressivo VACUUM FULL mytable
- que pode encontrar os mesmos problemas de simultaneidade, pois esse formulário também adquire um bloqueio exclusivo. Você pode tentar o pg_repack ...
Começaria por inspecionar possíveis problemas com índices, gatilhos, chave estrangeira ou outras restrições, especialmente as que envolvem a coluna. Especialmente um índice corrompido pode estar envolvido? Tente REINDEX TABLE mytable;
ou DROP
todos eles e adicione-os novamente ALTER TABLE
na mesma transação .
Tente executar o comando à noite ou sempre que não houver muita carga.
Um método de força bruta seria interromper o acesso ao servidor e tente novamente:
Sem poder identificá-lo, a atualização para a versão atual ou a 9.4 futura em particular pode ajudar. Houve várias melhorias para tabelas grandes e para detalhes de bloqueio. Mas se houver algo quebrado no seu banco de dados, você provavelmente deve descobrir isso primeiro.
SET NOT NULL
não altera o tipo, apenas adiciona uma restrição - mas a restrição deve ser verificada na tabela e isso exige uma verificação completa da tabela. A versão 9.4 melhora alguns desses casos com bloqueios mais fracos, mas ainda é bastante pesado.