Eu tenho uma pergunta sobre o ALTER TABLE
comando em uma tabela muito grande (quase 30 milhões de linhas). Uma de suas colunas é a varchar(255)
e eu gostaria de redimensioná-la para a varchar(40)
. Basicamente, gostaria de alterar minha coluna executando o seguinte comando:
ALTER TABLE mytable ALTER COLUMN mycolumn TYPE varchar(40);
Não tenho nenhum problema se o processo for muito longo, mas parece que minha tabela não é mais legível durante o comando ALTER TABLE. Existe uma maneira mais inteligente? Talvez adicione uma nova coluna, copie valores da coluna antiga, solte a coluna antiga e finalmente renomeie a nova?
Qualquer pista será muito apreciada! Desde já, obrigado,
Nota: Eu uso o PostgreSQL 9.0.
postgresql
varchar
alter-table
Labynocle
fonte
fonte
resizing
não fará com que a mesa ocupe menos espaço?varchar(255)
ao PostgreSQL, ele não alocará 255 bytes para um valor cujo comprimento real seja 40 bytes. Alocará 40 bytes (mais alguma sobrecarga interna). A única coisa quebe changed by the
ALTER TABLE` é o número máximo de bytes que você pode armazenar nessa coluna sem obter um erro do PG.Respostas:
Há uma descrição de como fazer isso em Redimensionar uma coluna em uma tabela do PostgreSQL sem alterar os dados . Você precisa hackear os dados do catálogo do banco de dados. A única maneira de fazer isso oficialmente é com ALTER TABLE e, como você observou, as alterações travam e reescrevem a tabela inteira enquanto estiver em execução.
Leia a seção Tipos de caracteres dos documentos antes de alterar isso. Todos os tipos de casos estranhos que você deve conhecer aqui. A verificação do comprimento é feita quando os valores são armazenados nas linhas. Se você hackear um limite mais baixo, isso não reduzirá o tamanho dos valores existentes. Você deve fazer uma varredura em toda a tabela, procurando por linhas em que o comprimento do campo seja> 40 caracteres após a alteração. Você precisará descobrir como truncar esses manualmente - para recuperar alguns bloqueios apenas nos de tamanho grande - porque se alguém tentar atualizar algo nessa linha, ele será rejeitado como muito grande agora, no ponto vai armazenar a nova versão da linha. Hilaridade segue para o usuário.
VARCHAR é um tipo terrível que existe no PostgreSQL apenas para cumprir com a parte terrível associada do padrão SQL. Se você não se importa com a compatibilidade de vários bancos de dados, considere armazenar seus dados como TEXT e adicione uma restrição para limitar seu tamanho. Restrições que você pode alterar sem esse problema de bloqueio / reescrita da tabela e podem fazer mais verificações de integridade do que apenas a verificação de comprimento fraco.
fonte
No PostgreSQL 9.1, existe uma maneira mais fácil
http://www.postgresql.org/message-id/[email protected]
fonte
Ok, provavelmente estou atrasado para a festa, MAS ...
Não é necessário redimensionar a coluna no seu caso!
O Postgres, diferentemente de outros bancos de dados, é inteligente o suficiente para usar apenas espaço suficiente para caber na sequência (mesmo usando a compactação para cadeias mais longas), portanto, mesmo que sua coluna seja declarada como VARCHAR (255) - se você armazenar cadeias de caracteres de 40 caracteres em Na coluna, o uso do espaço será de 40 bytes + 1 byte de sobrecarga.
( http://www.postgresql.org/docs/9.0/interactive/datatype-character.html )
A especificação de tamanho em VARCHAR é usada apenas para verificar o tamanho dos valores inseridos, não afeta o layout do disco. De fato, os campos VARCHAR e TEXT são armazenados da mesma maneira no Postgres .
fonte
Eu estava enfrentando o mesmo problema ao tentar truncar um VARCHAR de 32 para 8 e obter o
ERROR: value too long for type character varying(8)
. Quero ficar o mais próximo possível do SQL, porque estou usando uma estrutura semelhante a JPA, que talvez tenhamos que mudar para DBMS diferentes de acordo com as opções do cliente (o PostgreSQL é o padrão). Portanto, não quero usar o truque de alterar as tabelas do sistema.Acabei usando a
USING
instrução noALTER TABLE
:Como observou o @raylu,
ALTER
adquire um bloqueio exclusivo sobre a mesa, para que todas as outras operações sejam adiadas até que sejam concluídas.fonte
ALTER
adquire um bloqueio exclusivo sobre a mesa e evita todas as outras operaçõesAdicionar uma nova coluna e substituir uma nova por antiga funcionou para mim, no redshift postgresql, consulte este link para obter mais detalhes https://gist.github.com/mmasashi/7107430
fonte
Aqui está o cache da página descrita por Greg Smith. Caso isso também morra, a declaração alter é assim:
Onde sua tabela é TABLE1, a coluna é COL1 e você deseja configurá-la para 35 caracteres (o +4 é necessário para fins de legado de acordo com o link, possivelmente a sobrecarga mencionada por AH nos comentários).
fonte
se você colocar a alteração em uma transação, a tabela não deve ser bloqueada:
isso funcionou para mim rapidamente, alguns segundos em uma mesa com mais de 400 mil linhas.
fonte
ALTER
instrução? Não faz.COMMIT
. O wrapper só faz sentido se você deseja colocar mais comandos na mesma transação.Eu encontrei uma maneira muito fácil de alterar o tamanho, ou seja, a anotação @Size (min = 1, max = 50), que faz parte de "import javax.validation.constraints", ou seja, "import javax.validation.constraints.Size;"
fonte
Tente executar a seguinte tabela de alteração:
fonte