Guid vs INT - Quale è meglio come chiave primaria?


97

Sto leggendo i motivi per usare o meno Guide int.

intè più piccolo, più veloce, facile da ricordare, mantiene una sequenza cronologica. E per quanto riguarda Guid, l'unico vantaggio che ho trovato è che è unico. Nel qual caso a Guidsarebbe meglio di e inte perché?

Da quanto ho visto, intnon ha difetti se non per il limite numerico, che in molti casi è irrilevante.

Perché è stato Guidcreato esattamente ? In realtà penso che abbia uno scopo diverso da quello di servire come chiave primaria di una semplice tabella. (Qualche esempio di un'applicazione reale che utilizza Guidqualcosa?)

(Guid = UniqueIdentifier) ​​tipo su SQL Server


1
Piuttosto che chiave primaria , penso che intendi una chiave surrogata, cioè una chiave che non è la chiave naturale (quest'ultima è la chiave che usiamo nel mondo reale). Forse intendi indice cluster.
giorno

Ricorda anche la differenza tra (Primario) KEY e INDEX.
Allan S. Hansen,


2
" intnon ha difetti se non per il limite numerico, che in molti casi è irrilevante.": in realtà, in questo contesto di INT vs GUID, il limite superiore di un segno a 32 bit INTè del tutto irrilevante dato che il limite superiore di un segno , 64-bit BIGINTva ben oltre quasi tutti gli usi (ancora di più se si inizia a numerare dal limite inferiore; lo stesso vale per INT) e ha ancora la metà delle dimensioni di un GUID (8 byte anziché 16) e sequenziale.
Solomon Rutzky,

Risposte:


89

Questo è stato chiesto in Stack Overflow qui e qui .

Il post di Jeff spiega molto sui pro e contro dell'utilizzo del GUID.

GUID Pro

  • Unico su ogni tabella, ogni database e ogni server
  • Consente una facile fusione di record da diversi database
  • Consente una facile distribuzione di database su più server
  • È possibile generare ID ovunque, invece di dover andare di andata e ritorno nel database
  • La maggior parte degli scenari di replica richiede comunque colonne GUID

GUID Cons

  • È enorme 4 volte più grande del tradizionale valore dell'indice a 4 byte; questo può avere gravi conseguenze in termini di prestazioni e archiviazione se non stai attento
  • Da ingombrante a debug ( where userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
  • I GUID generati dovrebbero essere parzialmente sequenziali per le migliori prestazioni (ad esempio, newsequentialid()su SQL Server 2005+) e per consentire l'uso di indici cluster

Se si è certi delle prestazioni e non si prevede di replicare o unire i record, utilizzare inte impostare l'incremento automatico ( seed di identità in SQL Server ).


20
Un altro svantaggio dell'approccio GUID è che non è possibile utilizzarlo come identificatore per l'utente finale. Ti aspetti davvero che i tuoi utenti ti comunichino al telefono che hanno un problema con l'ordine "BAE7DF4-DDF-3RG-5TY3E3RF456AS10"? :)
Brann,

3
Se non si utilizzano guide sequenziali e la chiave primaria è raggruppata (la defaul di SQL Server), tutti gli inserimenti di dati saranno sparsi casualmente in tutta la tabella, portando a una massiccia frammentazione dei dati. Ciò presuppone che i dati vengano normalmente inseriti in una sorta di ordine, come cronologico.
datagod

6
Le guide sequenziali sono solo sequenziali fino al riavvio dell'istanza SQL. Quindi il primo valore sarà probabilmente più basso del precedente a causa del modo in cui viene generato il valore di root, causando nuovamente ogni sorta di problemi.
mrdenny,

20
@Brann Idealmente non dovresti dare i tuoi valori PK agli utenti finali, in primo luogo. So che è abbastanza comune farlo, ed è qualcosa che io stesso ho fatto in passato prima di aver imparato a non farlo. Ma dal momento che non dovrebbe essere fatto, quel particolare motivo per preferire INT al GUID non è valido.
Solomon Rutzky,

2
@ChadKuehn scelta UNIQUEIDENTIFIERsopra INTperché INTha un limite superiore è un ragionamento piuttosto scarsa in quanto essere senza limiti, mentre abbastanza vero, non è un pratico beneficio. Puoi facilmente raddoppiare la capacità effettiva di un INTavviandolo al limite inferiore (-2,14 miliardi) anziché a 1. Oppure, se i 4,3 miliardi completi non sono sufficienti, inizia con un BIGINTche è ancora solo 8 byte come rispetto a 16 per il GUID, ed è seqeuential.
Solomon Rutzky,

18

Se stai sincronizzando i tuoi dati con una fonte esterna, un GUID persistente può essere molto meglio. Un rapido esempio di dove stiamo usando un GUID è uno strumento che viene inviato al cliente per eseguire la scansione della propria rete ed eseguire determinate classi di rilevamento automatico, archiviare i record trovati e quindi tutti i record dei clienti sono integrati in un database centrale di nuovo dalla nostra parte. Se usassimo un numero intero, avremmo 7.398 "1" s, e sarebbe molto più difficile tenere traccia di quale "1" era quale.


3
I GUID sono sicuramente buoni come identificatori esterni, e manterrei un indice non cluster di quello come "chiave esterna". Vorrei comunque mantenere un int come "chiave interna" che è la base dell'indice cluster e delle relazioni di chiave esterna. Se qualcosa attraverserà un limite architettonico (es. Comunicare con un'altra app), apprezzo di avere qualcosa che non può essere confuso.
Greg,

15

Ho usato un approccio ibrido con successo. Le tabelle contengono ENTRAMBI una idcolonna intera di chiave primaria con incremento automatico E una guidcolonna. Il guidpuò essere usato come necessario globalmente univoco identificare la riga e idpuò essere utilizzato per le query, selezione e identificazione umana della fila.


3
Quale valore dà il GUID se il idgià è sufficiente per gli umani per identificare una riga?
Martin Smith,

6
L'id identifica la riga in questa tabella. Il GUID (almeno in teoria) identifica questa riga ovunque nell'universo noto. Nel mio progetto, i cellulari Android hanno ciascuno una copia strutturalmente identica della tabella su un database SQLite locale. La riga e il suo GUID sono generati ciascuno su Android. Quindi, quando Android è sincronizzato con il database back-end, la sua riga locale viene scritta nella tabella back-end senza timore di essere in conflitto con le righe create da qualsiasi altro dispositivo Android.
rmirabelle,

2
@MartinSmith Ho usato questo approccio da solo e funziona abbastanza bene. Il GUID è solo una chiave alternativa, con un indice non cluster, e viene passato dall'applicazione, ma risiede solo nella tabella primaria. Tutte le tabelle correlate sono correlate tramite INTPK. Trovo strano che questo approccio non sia molto più comune dato che è il migliore dei due mondi. Sembra che la maggior parte delle persone preferisca semplicemente risolvere i problemi in termini molto assolutisti, non rendendosi conto che il PK non deve essere un GUID per consentire all'app di utilizzare ancora i GUID per l'unicità globale e / o la portabilità.
Solomon Rutzky,

1
@rmirabelle Avevo pensato a questo approccio ed era esitante, ma la tua risposta mi ha convinto. Fondamentalmente mi trovo in una situazione in cui ho bisogno di avere un identificatore univoco per un oggetto di lavoro (che può entrare in rete da qualsiasi luogo), ma non voglio prima fare un giro di andata e ritorno nel database. I GUID sono una buona soluzione per questo, ma immagino che i JOIN diventeranno molto più lenti se non ho una chiave cluster sequenziale.
easuter,

1
@easuter Sono d'accordo con non aggiungere campi ID "solo per il gusto di farlo", come ad esempio nelle tabelle "bridge" di molti a molti in cui il PK dovrebbe essere un composto dei due FK che sono correlati. Ma qui non è un compromesso poiché il campo ID non è solo per il gusto di farlo. Permettere al sistema di funzionare in modo efficiente è abbastanza importante ;-). E, direi che nel tuo caso, poiché i GUID sono generati esternamente, quelli non sono garantiti unici, anche se pragmaticamente lo sono. Ma la responsabilità per l'integrità dei dati è una ragione sufficiente per avere GUID come chiave alternativa e ID come PK nel tuo caso :)
Solomon Rutzky,

1

Alcune best practice là fuori menzionano ancora che dovresti usare un tipo di dati che accolga con meno memoria possibile l'intero insieme di valori che userai. Ad esempio, se lo si utilizza per memorizzare il numero di datori di lavoro in una piccola impresa e è improbabile che arrivi a 100, nessuno suggerirebbe di utilizzare un valore bigint mentre int (anche smallint) lo farebbe.

Naturalmente, lo svantaggio di questo è come "Di 'no alla scalabilità!"


Inoltre, so che questo non è totalmente correlato, ma c'è un altro fattore al riguardo. Se non eccessivo, di solito provo a raccomandare di utilizzare una chiave primaria non generata automaticamente, se ha senso. Ad esempio, se stai salvando le informazioni del conducente, non preoccuparti di creare una nuova colonna generata automaticamente per "ID", basta usare il numero di licenza.

So che questo sembra davvero ovvio, ma vedo che l'essere dimenticato abbastanza spesso.

Per il contesto: questa parte della risposta è stata indirizzata da un approccio teorico dei dati, in cui si desidera che il proprio PK sia l'identificatore univoco dei dati per un record. Il più delle volte li creiamo quando esistono già, da cui la risposta precedente.

Tuttavia, è molto raro che tu possa avere uno stretto controllo su questi punti dati e, in quanto tale, potrebbe essere necessario apportare correzioni o aggiustamenti. Non puoi farlo con le chiavi primarie (beh, puoi, ma può essere una seccatura).

Grazie @VahiD per i chiarimenti.


l'uso di chiavi primarie significative non è affatto raccomandato, si consideri lo scenario seguente, qualcuno ha inserito un numero di licenza errato e hai usato questo ID in 3-4 tabelle come chiave esterna, come si corregge questo errore? la semplice modifica del numero di licenza non potrebbe essere sufficiente in questo caso.
VahiD

1
Divertente: ho letto il tuo commento e ho pensato "sì, certo", poi sono tornato a leggere la mia risposta e ho pensato "l'ho detto"? Divertente come cambiano le cose in un paio d'anni. Probabilmente provenivo da un background più teorico, ma a meno che tu non abbia uno stretto controllo su di esso (raramente) non offre molti vantaggi. Aggiornerò la risposta.
Alpha,

votazione per lo sviluppo negli anni :)
VahiD

1

L'uso degli ID di incremento automatico potrebbe contenere informazioni sull'attività aziendale. Se gestisci un negozio e utilizzi order_idper identificare pubblicamente un acquisto, allora chiunque può scoprire il tuo numero mensile di vendite con una semplice aritmetica.


0

Un'altra cosa su come vengono generati i GUID. mrdenny ha giustamente sottolineato che anche se si utilizza newsequentialid (), il riavvio delle istanze fa sì che i nuovi valori inizino con i "buchi" lasciati indietro nell'elaborazione precedente. Un'altra cosa che influenza i GUID "sequenziali" è la scheda di rete. Se ricordo bene, l'UID della NIC viene utilizzato come parte dell'algoritmo GUID. Se viene sostituita una scheda NIC, non esiste alcuna garanzia che l'UID avrà un valore più elevato per mantenere l'aspetto sequenziale delle cose. Inoltre, non sono sicuro di come più schede di rete possano influenzare l'assegnazione dei valori utilizzando l'algoritmo.

Solo un pensiero e spero di ricordare correttamente. Vi auguro una buona giornata!


2
Benvenuto in Database Administrator, bobo8734. Potresti trovare alcune fonti per questi commenti? Se non sei sicuro di loro, forse sarebbero meglio serviti come commento (quando ne hai il rappresentante) che come risposta autonoma.
LowlyDBA,

-6

Utilizza entrambi

Utilizzare int / Bigint per la chiave primaria in quanto è facile da mantenere e utilizzare come relazioni di chiave esterna.

Ma associare una colonna al GUID in modo che ogni riga abbia anche una colonna univoca


2
Spiegare il tuo ragionamento dietro questo suggerimento non farebbe male a nessuno, ne sono sicuro.
Andriy M,

Il GUID è lungo 36 caratteri e sarà difficile da leggere se stai cercando un caso specifico ..
Abdul Hannan Ijaz

1
Va bene, ma questo non spiega davvero perché l'OP dovrebbe usare entrambi inte guid, come stai suggerendo nella tua risposta. E inoltre, non stavo parlando di spiegare il tuo suggerimento solo a me - il mio punto era che potresti voler aggiornare la tua risposta . A proposito, sei consapevole che un altro risponditore ha già suggerito lo stesso (più o meno) come te ?
Andriy M,

Sì, intendevo la stessa cosa ... cool BTW :)
Abdul Hannan Ijaz
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.