O que fazer quando um campo em uma tabela se aproxima do número inteiro máximo de 32 bits com ou sem sinal?

14

Em qualquer banco de dados que mantenha registros de usuários na forma de um campo de incremento automático exclusivo (por exemplo, mensagens entre usuários) ... o que fazer quando chegar a hora e se aproximar do número máximo assinado ou não assinado do tipo de dados atual? (Um INT de 32 bits)? Estou supondo que o servidor de banco de dados estourará quando tentar atribuir o número (2∧32) -1 à próxima entrada, portanto, como evitar que isso aconteça (sem alterar o tipo de dados, apenas para fins de pergunta) e continuar adicionando registros? O que você faria?

Por que eu usaria INTs e não, por exemplo, VARCHARS?

Já se passaram vários dias desde que me fiz essa pergunta hipotética e gostaria de saber o que um profissional faria.

AeroCross
fonte

Respostas:

12

Geralmente, você usaria números inteiros em vez de varchars, porque eles consomem menos espaço, têm um padrão de classificação bem compreendido, são rápidos para indexar etc. Inteiros são tipos de dados naturais de uma CPU e, portanto, o desempenho geralmente é ideal. Normalmente, um número inteiro tem 4 bytes, equivalente a apenas 4 caracteres em um varchar (não unicode).

Se você estava preocupado com a falta de espaço com um tipo INT, tente o BIGINT, que fornece números de 8 bytes. O limite é muito grande e você provavelmente não terá mais espaço em disco antes de atingir esse limite de registros :-) O desempenho do BIGINT também será muito bom, especialmente porque muitos servidores agora também têm 64 bits .

A resposta para a primeira parte da sua pergunta sobre o que acontece quando você acaba com as INTs não é simples, especialmente como você disse sem alterar o tipo de dados para BIGINT. Basicamente, não há muito o que você possa fazer, e o que você poderá fazer é muito limitado pela natureza dos dados em seu banco de dados. Quais registros são de chave estrangeira para esses dados? Você ainda precisa de todos os dados nessa tabela e dos registros relacionados? Supondo que você possa arquivar muitos dados iniciais (e seus dados relacionados), a única coisa que posso sugerir é mover os dados para fora da tabela (digamos os primeiros 1 a X milhões de registros) e, em seguida, redefinindo a semente de identidade para 1. Há vários tipos de motivos que eu não recomendaria - por exemplo, existem muitos bits de código que vi que fazem coisas como verificar o valor máximo de um campo de ID, para ver o que acabou de ser adicionado, e isso não funcionaria (e não deve ser feito). Além disso, as pessoas assumem que o registro N foi criado antes de N + 1. Nenhuma resposta fácil, eu acho.

Por fim, não conheço o MySQL, mas o SQL Server causaria um erro de estouro se você atingisse o limite.

Miles D
fonte
1
Estou satisfeito com uma resposta tão detalhada. Obrigado pela explicação do negócio VARCHAR, INT e BIGINT. Como a pergunta é hipotética, pergunto-me o que aconteceria se também fosse atingido o limite BIGINT. A questão foi levantada por um post que eu vi sobre o Facebook usando o INT e atingindo o limite, e eu vejo isso como totalmente possível. O arquivamento funcionaria ou criaria uma segunda tabela com uma declaração condicional (que, como você disse, também exigiria a atualização dos scripts e seria bastante complexo). No geral, ótima resposta. Eu aprecio o tempo gasto.
AeroCross
9

Um ponto esquecido é que muitas pessoas iniciam o número ou a identidade automática em 1, perdendo imediatamente metade do intervalo possível (para assinados)

Você simplesmente redefiniria o número para começar em -1, incrementando -1 nesse caso.

Indiscutivelmente, se você esperava preencher sua coluna de identidade, deveria ter projetado isso e usado um tipo de dados mais amplo no início.

Veja esta pergunta recente sobre SO: SQL Server 2008: o que aconteceu se a identidade ultrapassar um valor máximo de int?

gbn
fonte
É lógico que eu usaria um tipo de dados mais amplo (para uma tabela com essa quantidade de dados), mas, como se tratava de uma pergunta hipotética, eu queria ter uma ideia. Se for assinado, isso pode funcionar (mas eu seria um pouco estranho ter uma chave primária com números negativos, IMHO) e acho que é bem inteligente. Isso daria tempo para o DBA arquivar os dados positivos e começar de novo. Se não assinado, bem ... problemas.
AeroCross
Como alternativa ao uso de um incremento de -1 a partir de -1, inicie em (-2147483648) e aumente em 1. Mas sim, depois de cruzar INT_MAX, você estará bem organizado e precisará revisitar o design e remover o índice antigo que o substitui com um novo maior. e se você passar BIGINT não assinado, eu quero trabalhar na sua equipe;)
jcolebrand
O PostgreSQL usa sequências para gerar números de identificação; a instrução CREATE SEQUENCE permite especificar CYCLE, que será contornado apenas se você atingir o valor máximo. (Ou o valor mínimo, se você estiver indo na outra direção.) A opção CYCLE está nos padrões SQL agora. (Desde pelo menos 2003.)
Mike Sherrill 'Cat Recall'
4

Estouro BIGINT? Haha Primeiro, descubra como alcançar a imortalidade. INT UNSIGNED (4 bilhões) já é difícil de alcançar. 100 INSERTs por segundo chegariam perto do transbordamento da INT em um ano. O BIGINT levaria vários bilhões de anos.

Para corrigir: ALTER TABLE foo MODIFY COLUMN id BIGINT NÃO ASSINADO NÃO NULL AUTO_INCREMENT; Mas isso levará horas, porque ele será copiado sobre a tabela (que possui quase 4 bilhões de linhas, certo?) E reconstruirá todos os índices secundários. Planejar com antecedência.

Geralmente, quando você tenta armazenar um número muito grande para um campo (por exemplo, 999 em um TINYINT UNSIGNED), ele silenciosamente o limita ao máximo para o campo (255 neste caso). Pode haver um "Aviso", mas a maioria das pessoas não se preocupa em verificar os avisos. Se for um campo ÚNICO ou houver CHAVES ESTRANGEIRAS, você poderá receber um erro mais sério.

CHAR ou VARCHAR é silenciosamente truncado para o espaço disponível.

Rick James
fonte