Cosa fare quando un campo in una tabella si avvicina all'intero massimo a 32 bit con o senza segno?


14

In un determinato database che contiene record utente sotto forma di un campo di incremento automatico univoco (a titolo di esempio, messaggi tra utenti) ... cosa fare quando arriva il momento e si avvicina al numero massimo di segni o non firmati del tipo di dati corrente? (Un INT a 32 bit)? Sto indovinando che il server di database traboccerebbe quando tenta di assegnare il numero (2∧32) -1 alla voce successiva, quindi, come evitare che ciò accada (senza cambiare il tipo di dati, per il bene della domanda) e continuare ad aggiungere record? Cosa faresti?

Perché dovrei usare INT e non, ad esempio, VARCHARS?

Sono passati diversi giorni da quando mi sono posto questa ipotetica domanda e vorrei sapere cosa farebbe un professionista.

Risposte:


12

In genere useresti numeri interi anziché varchar perché consumano meno spazio, hai ben compreso che il modello di ordinamento è veloce da indicizzare, ecc. I numeri interi sono tipi di dati naturali di una CPU e quindi le prestazioni sono generalmente ottimali. In genere un numero intero è di 4 byte, equivalenti a soli 4 caratteri in un varchar (non unicode).

Se ti preoccupavi di rimanere senza spazio con un tipo INT, prova BIGINT, che ti dà numeri a 8 byte. Il limite è piuttosto grande e probabilmente ti verrebbe a corto di spazio su disco prima di raggiungere quel limite di record :-) Anche le prestazioni di BIGINT saranno molto buone, soprattutto perché molti server ora sono anche a 64 bit .

La risposta alla prima parte della tua domanda su cosa succede quando si esaurisce INTs non è semplice, specialmente come hai detto senza cambiare il tipo di dati in BIGINT. Fondamentalmente non c'è molto che puoi fare e ciò che potresti essere in grado di fare è molto limitato dalla natura dei dati nel tuo database. Quali record hanno una chiave esterna per questi dati? Hai ancora bisogno di tutti i dati in quella tabella e i relativi record? Partendo dal presupposto che potresti archiviare molti dei dati iniziali (e dei relativi dati), l'unica cosa che posso suggerire è di spostare i dati fuori dalla tabella (diciamo i primi da 1 a X milioni di record), quindi reimpostare il seed dell'identità su 1. Ci sono molti tipi di ragioni, anche se non lo consiglierei, ad esempio ci sono molti bit di codice che ho visto che fanno cose come controllare il valore massimo di un campo ID, per vedere cosa è stato appena aggiunto e che non funzionerebbe (e non dovrebbe essere fatto). Inoltre, si presume che il record N sia stato creato prima di N + 1. Nessuna risposta facile penso.

Infine, non so di MySQL, ma SQL Server darebbe un errore di overflow se raggiungessi il limite.


1
Sono contento di una risposta così dettagliata. Grazie per la spiegazione dell'accordo VARCHAR, INT e BIGINT. Poiché la domanda è ipotetica, mi chiedo cosa succederebbe se si raggiungesse anche il limite BIGINT. La domanda è stata sollevata da un post che ho visto su Facebook usando INT e raggiungendo il limite, e lo vedo come totalmente possibile. L'archiviazione funzionerebbe o la creazione di una seconda tabella con un'istruzione condizionale (che, come hai detto, richiederebbe anche l'aggiornamento degli script e sarebbe piuttosto complessa). Nel complesso, un'ottima risposta. Apprezzo il tempo impiegato.
AeroCross

9

Un punto trascurato è che molte persone iniziano il numero automatico o l'identità su 1, perdendo immediatamente metà del range possibile (per il segno)

Dovresti semplicemente ridefinire il numero per iniziare da -1, incrementare -1 in questo caso.

Probabilmente, se ti aspettavi di riempire la colonna della tua identità, avresti dovuto progettarlo e utilizzare un tipo di dati più ampio all'inizio.

Vedi questa recente domanda su SO: SQL Server 2008: cosa è successo se l'identità supera un valore massimo di int?


È logico che userei un tipo di dati più ampio (per una tabella che farebbe come QUESTA quantità di dati), ma dal momento che era una domanda ipotetica, volevo un po 'di intuizione. Se è firmato, potrebbe funzionare (ma sarebbe un po 'strano avere una chiave primaria con numeri negativi, IMHO) e penso che sia abbastanza intelligente. Darebbe tempo al DBA per archiviare i dati positivi e ricominciare. Se non firmato, beh ... problemi.
AeroCross,

In alternativa all'utilizzo di un incremento di -1 da -1, inizia da (-2147483648) e aumenta di 1. Ma sì, dopo aver attraversato INT_MAX allora sei abbastanza ben informato e devi rivisitare il design e rimuovere il vecchio indice sostituendolo con una nuova più grande. e se passi BIGINT non firmato allora voglio venire a lavorare nella tua squadra;)
jcolebrand

PostgreSQL utilizza sequenze per generare numeri ID; l'istruzione CREATE SEQUENCE ti consente di specificare CYCLE, che andrà a finire se raggiungi il valore massimo. (O il valore minimo, se stai andando nella direzione opposta.) L'opzione CYCLE è ora negli standard SQL. (Almeno dal 2003.)
Mike Sherrill "Cat Recall",

4

Overflow BIGINT? Haha. Prima di tutto, scopri come raggiungere l'immortalità. INT UNSIGNED (4 miliardi) è abbastanza difficile da raggiungere. 100 INSERTI al secondo si avvicinerebbero allo straripamento di INT in un anno. BIGINT richiederebbe diversi miliardi di anni.

Per risolvere: ALTER TABLE foo MODIFY COLUMN id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT; Ma ci vorranno ore perché copierà sul tavolo (che ha quasi 4 miliardi di righe, giusto?) E ricostruirà tutti gli indici secondari. Pianificare in anticipo.

Generalmente quando si tenta di memorizzare un numero troppo grande per un campo (ad es. 999 in un TINYINT UNSIGNED), lo bloccherà silenziosamente al massimo per il campo (255 in questo caso). Potrebbe esserci un "Avviso", ma molte persone non si preoccupano di controllare gli avvisi. Se si tratta di un campo UNICO o ci sono CHIAVI STRANIERE, potresti ricevere un errore più grave.

CHAR o VARCHAR viene troncato silenziosamente nello spazio disponibile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.