Come ti piacciono le tue chiavi primarie? [chiuso]


88

In una discussione piuttosto animata nel mio team mi è stato fatto pensare a ciò che piace alla maggior parte delle persone come chiavi primarie. Avevamo i seguenti gruppi:

  1. Int / BigInt quali autoincrement sono chiavi primarie abbastanza buone.
  2. Dovrebbero esserci almeno 3 colonne che compongono la chiave primaria.
  3. ID, GUID e identificatori di riga leggibili dall'uomo dovrebbero essere trattati in modo diverso.

Qual è l'approccio migliore per i PK? Sarebbe fantastico se potessi giustificare la tua opinione. C'è un approccio migliore di quello sopra?

EDIT: Qualcuno ha un semplice campione / algoritmo per generare identificatori leggibili dall'uomo per le righe che si ridimensionano bene?


1
Poiché questo è soggettivo, dovrebbe essere un wiki della comunità
John Sheehan

2
"Ci dovrebbero essere almeno 3 colonne che compongono la chiave primaria"? Cosa significa questo? Potete fornire un'ulteriore definizione? O fa parte di # 3?
S.Lott

@ S.Lott PK(NEWID(),NEWID(),NEWID());-)

@ pst: Perché questo è un requisito? Perché devono esserci tre colonne in una PK? Perché uno o quattro?
S.Lott

Ho potuto vedere un aspetto PK a tre colonne come ... LocalID (Auto increment int), GlobalID (GUID), ForeignId (chiave esterna come RolesType), ecc. LocalID + ForiegnId potrebbe essere una combinazione di tasti composti. La Guida viene utilizzata per altri siti Web / servizi. Personalmente non lo farei, userei solo Guid + ForiegnId.
Jerad

Risposte:


76

Se hai intenzione di eseguire qualsiasi sincronizzazione tra database con app connesse occasionalmente, dovresti utilizzare GUID per le tue chiavi primarie. È un po 'una seccatura per il debug, quindi a parte questo caso tendo ad attenermi agli int che autoincrement.

Gli int di incremento automatico dovrebbero essere il tuo valore predefinito e non usarli dovrebbe essere giustificato.


3
Non è necessario un GUID, basta modificare il passaggio su 10 o 20 o su tutti i server con cui sarà necessario sincronizzarsi in futuro.
Robert C. Barth

43
Almeno il 90% delle volte, un GUID non è necessario e spreca spazio.
Jonathan Leffler

8
Penso seriamente che i GUID siano eccessivi. Non ho mai avuto bisogno di avere GUID come chiavi primarie ancora.
Cyril Gupta

7
Oppure, invece di sprecare spazio e rischiare la collisione con un GUID, crea una chiave composita della chiave primaria originale e un piccolo identificatore, dove il piccolo identificatore è diverso per ogni sorgente di sincronizzazione.
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

5
Un negozio per cui ho lavorato utilizzava GUID per tutto, anche quando erano disponibili identificatori pubblici, come i codici ISO del paese o della lingua. E anche quando un booleano o CHAR(1)sarebbe stato sufficiente, come per sex. Inutile dire che è stato un incubo con cui lavorare.
Lumi

56

Non vedo una risposta che indichi (quello che io considero) il punto veramente fondamentale - vale a dire, che una chiave primaria è ciò che garantisce che non avrai due voci nella tabella per la stessa entità del mondo reale (come modellato nel database). Questa osservazione aiuta a stabilire quali sono le buone e quali le cattive scelte per la chiave primaria.

Ad esempio, in una tabella di nomi e codici di stato (USA), il nome o il codice potrebbe essere la chiave primaria: costituiscono due chiavi candidate diverse e una di esse (normalmente la più corta - il codice) viene scelta come chiave primaria. Nella teoria delle dipendenze funzionali (e delle dipendenze unite - da 1NF a 5NF - sono le chiavi candidate che sono cruciali piuttosto che una chiave primaria.

Per un controesempio, i nomi umani generalmente sono una cattiva scelta per la chiave primaria. Ci sono molte persone che si chiamano "John Smith" o altri nomi simili; anche tenendo conto dei secondi nomi (ricorda: non tutti ne hanno uno, ad esempio io no), c'è molto spazio per la duplicazione. Di conseguenza, le persone non usano i nomi come chiavi primarie. Inventano chiavi artificiali come il numero di previdenza sociale (SSN) o il numero del dipendente e le usano per designare l'individuo.

Una chiave primaria ideale è breve, unica, memorabile e naturale. Di queste caratteristiche, l'unicità è obbligatoria; il resto deve flettere dati i vincoli dei dati del mondo reale.

Quando si tratta di determinare la chiave primaria di una data tabella, quindi, devi guardare a cosa rappresenta quella tabella. Quale serie o serie di valori di colonna nella tabella identifica in modo univoco ciascuna riga nella tabella? Quelle sono le chiavi candidate. Ora, se ogni chiave candidata è composta da 4 o 5 colonne, potresti decidere che quelle sono troppo goffe per creare una buona chiave primaria (principalmente per motivi di brevità). In queste circostanze, potresti introdurre una chiave surrogata, un numero generato artificialmente. Molto spesso (ma non sempre) un semplice intero a 32 bit è sufficiente per la chiave surrogata. Quindi designate questa chiave surrogata come chiave primaria.

Tuttavia, devi comunque assicurarti che le altre chiavi candidate (poiché anche la chiave surrogata è una chiave candidata, così come la chiave primaria scelta) siano tutte mantenute come identificatori univoci, normalmente ponendo un vincolo univoco su quei set di colonne.

A volte, le persone trovano difficile identificare ciò che rende unica una riga, ma dovrebbe esserci qualcosa da fare, perché la semplice ripetizione di un'informazione non la rende più vera. E se non stai attento e ottieni due (o più) righe che pretendono di memorizzare le stesse informazioni, e quindi devi aggiornare le informazioni, c'è il pericolo (specialmente se usi i cursori) che aggiorni solo una riga piuttosto che ogni riga, quindi le righe non sono sincronizzate e nessuno sa quale riga contiene le informazioni corrette.

Questa è una visione piuttosto dura, per alcuni aspetti.

Non ho particolari problemi con l'utilizzo di un GUID quando sono necessari, ma tendono ad essere grandi (come 16-64 byte) e vengono utilizzati troppo spesso. Molto spesso è sufficiente un valore di 4 byte perfettamente buono. L'uso di un GUID in cui un valore di 4 byte sarebbe sufficiente spreca spazio su disco e rallenta anche l'accesso indicizzato ai dati poiché ci sono meno valori per pagina di indice, quindi l'indice sarà più profondo e sarà necessario leggere più pagine per arrivare al informazione.


10
Per quanto riguarda il tuo campione con nomi di stati statunitensi preferirei una chiave surrogata separata, semplicemente perché i codici sono qualcosa al di fuori del tuo controllo. Se dovessero cambiare per qualsiasi motivo, hai un problema.
Dirk Vollmar

(segue) Ad esempio, la Germania ha sostituito un sistema di codice postale a 4 cifre con un sistema a 5 cifre negli anni '90 dopo la riunificazione.
Dirk Vollmar

@divo: sono un forte sostenitore delle chiavi artificiali / surrogate, ma nemmeno io vedo la modifica del codice postale da 4 a 5 cifre come un buon esempio. I codici postali non sono generalmente utilizzati come chiavi per nulla. (Quando è stata l'ultima volta che hai dovuto interrogare una tabella PostalCode per scoprire qualcosa su quel codice? No, è quasi esclusivamente utilizzato come parte di un indirizzo senza essere referenziato in altre tabelle. Direi che il tuo suggerimento è quasi alla pari con l'utilizzo chiavi surrogate per gli indirizzi stessi.)
ErikE

@Emtucifor: Sì, forse ZIP non è un esempio molto pratico, ma il mio punto era che se una parte della tua chiave surrogata è fuori dal tuo controllo e cambia per qualsiasi motivo, sei nei guai. Pensa a qualcuno che crea un nuovo schema di numero di previdenza sociale, un nuovo schema ISSN o - forse più realistico - un'azienda che decide di creare un nuovo sistema di identificazione del prodotto dopo una fusione, assegnando nuovi numeri di dipendenti ai propri dipendenti per regolare la loro crescita ecc. tutti solo esempi di fantasia, ma, come mostra il mio precedente esempio con ZIP, a volte un sistema ben consolidato potrebbe cambiare.
Dirk Vollmar

2
Il tuo primo punto è corretto. C'è un nome per questo vincolo. Si chiama "integrità dell'entità". EI richiede che ogni entità abbia un'identità unica. Le chiavi primarie spesso soddisfano questo requisito, tranne quando viene utilizzato il numero automatico. Con autonumber, puoi ottenere due righe identiche, ad eccezione dell'autonumber. Questo di solito viola l'integrità dell'entità.
Walter Mitty

26

Questa è solo una questione religiosa perché le persone cercano una risposta giusta universale. Il fatto che sia il tuo team che questo thread SO mostrino così tanto disaccordo dovrebbe essere un indizio che ci sono buone ragioni per usare tutte le soluzioni che descrivi, in circostanze diverse.

  • Le chiavi surrogate sono utili quando nessun altro attributo o insieme di attributi nella tabella è adatto per identificare le righe in modo univoco.
  • Le chiavi naturali sono preferite, quando possibile, per rendere la tabella più leggibile dall'uomo. Le chiavi naturali consentono anche alla chiave esterna in una tabella dipendente di contenere un valore reale invece di un ID surrogato. Ad esempio, quando hai bisogno di memorizzare state(CA, TX, NY) potresti anche usare una char(2)chiave naturale invece di un int.
  • Usa chiavi primarie composte dove appropriato. Non aggiungere una " id" chiave surrogata inutilmente quando esiste una " " chiave composta perfettamente buona (questo è particolarmente vero nelle tabelle molti-a-molti). Un mandato per una chiave a tre colonne in ogni tabella è un'assurdità assoluta.
  • I GUID sono una soluzione quando è necessario preservare l'unicità su più siti. Sono anche utili se hai bisogno che i valori nella chiave primaria siano univoci, ma non ordinati o consecutivi.
  • INT vs. BIGINT: non è comune che una tabella richieda un intervallo di 64 bit per le chiavi primarie, ma con la crescente disponibilità di hardware a 64 bit non dovrebbe essere un peso e offre maggiori garanzie di non overflow. INT è ovviamente più piccolo, quindi se lo spazio è limitato può dare un leggero vantaggio.

6
Non sono d'accordo per quanto una persona possa farlo. Le chiavi naturali sono orribili. E se si volessero modificare i dati? Oh, non puoi. Scrivere join su chiavi naturali composite è un problema. Portare quella chiave composita a tutte le tabelle correlate è uno spreco.
Robert C. Barth

2
@Robert: leggi di "ON UPDATE CASCADE". Ma capisco quello che stai dicendo e sono d'accordo che è meglio usare una chiave surrogata la maggior parte delle volte, perché gli attributi sono soggetti a modifiche e non sono univoci.
Bill Karwin

1
Le chiavi primarie dovrebbero essere immutabili. Gli aggiornamenti a cascata in questo caso sono solo un brutto trucco per una cattiva decisione di progettazione. Le chiavi naturali non sono MAI preferite. Lo stesso per le chiavi composite, che si diffondono come una piaga. Chiunque abbia più di 3 mesi di esperienza nello sviluppo di database lo saprebbe.
FDCastel

7
@FD: Non sono d'accordo con la tua dichiarazione inequivocabile, e ho sviluppato con database SQL dal 1992. Ma di certo è vero che le chiavi surrogate riescono meglio a rimanere immutabili.
Bill Karwin,

20

Mi piace il blog di The Database Programmer come fonte per questo tipo di informazioni.

3 colonne per una chiave primaria? Direi che le colonne dovrebbero avere vincoli univoci appropriati come richiesto dalle regole di business, ma avrei comunque una chiave surrogata separata. Le chiavi composte significano che la logica aziendale entra nella chiave. Se la logica cambia, l'intero schema è rovinato.


2
Hanno cambiato il loro collegamento, ecco il segnalibro aggiornato: database-programmer.blogspot.com/2008/09/…
Bryan Rehbein

Ho appena ereditato un progetto come questo. E la prima cosa che volevano fare ha fatto saltare in aria lo schema. Chiavi surrogate FTW. Logica aziendale nel tuo DB FTL.
Jason


11

Un po 'fuori tema, ma mi sento in dovere di intervenire con ...

Se la tua chiave primaria è un GUID, non renderlo un indice cluster . Poiché i GUID non sono sequenziali, i dati verranno riorganizzati su disco durante quasi ogni inserimento. (Yuck.) Se si utilizzano GUID come chiavi primarie, dovrebbero essere indici non cluster.


1
Punto molto positivo: è necessario distinguere tra il concetto LOGICO di una chiave primaria (potrebbe essere valido utilizzare un GUID per quello, specialmente se è coinvolta la replica) e il concetto FISICO della chiave di clustering - che non dovrebbe MAI essere un GUID poiché porta a un'eccessiva frammentazione dell'indice
marc_s

3
Questo infatti non è accurato. I dati verranno inseriti in ordine, il che, data la natura casuale del GUID, potrebbe finire per essere ovunque nella tabella. Nella remota possibilità che non ci sia spazio, si verificherà una divisione di pagina, ma certamente non "si riorganizza su disco durante ogni inserimento" nemmeno si chiude.
Ralph Shillington

@ Ralph, hai ragione, non TUTTI gli inserti, ma abbastanza da causare un calo di prestazioni 20x. sql-server-performance.com/articles/per/…
Portman

La funzione newsequentialid () di SQL Server risolve il problema della frammentazione dell'indice con i GUID (sebbene 24 byte siano ancora un po 'eccessivi se non è assolutamente necessaria l'unicità globale). Vedi msdn.microsoft.com/en-us/library/ms189786.aspx.
ErikE

10

Vado sempre con la chiave surrogata. Una chiave surrogata (in genere una colonna Identity, autoincrement o GUID) è quella in cui la chiave non è presente nei dati stessi. Una chiave naturale, d'altra parte, è quella che, da sola, identifica in modo univoco la riga. Per quanto posso dire nella vita, non ci sono quasi nessuna vera chiave naturale. Nemmeno cose come SSN negli Stati Uniti è una chiave naturale. Le chiavi primarie composite sono un disastro in attesa di accadere. Non puoi modificare nessuno di quei dati (che è il principale svantaggio di qualsiasi chiave naturale, composta o meno), ma il peggio è che con una chiave composta, ora devi perpetuare quei dati chiave in ogni tabella correlata. Che spreco gigante.

Ora, per la selezione della chiave surrogata, mi attengo alle colonne di identità (lavoro principalmente in MS SQL Server). I GUID sono troppo grandi e Microsoft consiglia di non utilizzarli come PK. Se hai più server, tutto ciò che devi fare è fare l'incremento di 10 o 20 o qualunque cosa pensi sia il numero massimo di server che dovrai mai sincronizzare / espandere, e solo aumentare il seme per ogni tabella su ogni server successivo e non avrai mai una collisione di dati.

Ovviamente, a causa dell'incremento, rendo la colonna Identity un BigInt (altrimenti noto come long [64 bits]).

Facendo un po 'di matematica, anche se incrementi 100, puoi comunque avere 92.233.720.368.547.758 (> 92 quadrilioni) righe nella tua tabella.


9

Penso che l'uso della parola "Primary", nella frase "Primary" Key, sia in un senso reale, fuorviante.

Innanzitutto, utilizza la definizione che una "chiave" è un attributo o un insieme di attributi che devono essere univoci all'interno della tabella,

Quindi, avere qualsiasi chiave serve a diversi scopi spesso reciprocamente incoerenti.

  1. Da utilizzare come condizioni di join a uno o più record nelle tabelle figlie che hanno una relazione con questa tabella padre. (Definizione esplicita o implicita di una chiave esterna in quelle tabelle figlie)
  2. (correlato) Garantire che i record figlio debbano avere un record padre nella scheda padre; e (La tabella figlio FK deve esistere come chiave nella tabella padre)
  3. Per aumentare le prestazioni delle query che necessitano di individuare rapidamente un record / riga specifico nella tabella.

  4. Per garantire la coerenza dei dati impedendo l'inserimento di righe duplicate che rappresentano la stessa entità logica nella tabella. (Questa è spesso chiamata chiave "naturale" e dovrebbe essere costituita da attributi di tabella (entità) che sono relativamente invarianti.)

Chiaramente, qualsiasi chiave non significativa e non naturale (come un GUID o un intero generato automaticamente è totalmente incapace di soddisfare # 4.

Ma spesso, con molte (la maggior parte) tabelle, una chiave totalmente naturale che può fornire # 4 sarà spesso composta da più attributi e sarà eccessivamente larga, o così ampia che usarla per gli scopi # 1, # 2 o # 3 causerà inaccettabile conseguenza delle prestazioniec.

La risposta è semplice. Usali entrambi. Usa una semplice chiave integrale di generazione automatica per tutti i join e gli FK in altre tabelle figlie, ma assicurati che ogni tabella che richiede la coerenza dei dati (pochissime tabelle non lo fanno) abbia una chiave univoca naturale alternativa che impedirà gli inserimenti di righe di dati incoerenti. .. Inoltre, se hai sempre entrambi, allora tutte le obiezioni contro l'uso di una chiave naturale (cosa succede se cambia? Devo cambiare ogni punto in cui viene indicato come FK) diventano discutibili, poiché non la stai usando per quello. .. Lo stai usando solo nella tabella in cui è un PK, per evitare dati duplicati incoerenti ...

Per quanto riguarda i GUID, fai molta attenzione a usarli, poiché l'uso di guide in un indice può compromettere la frammentazione dell'indice. Gli algoritmi più comuni utilizzati per crearli collocano la parte "casuale" del guid nelle posizioni di bit più significative ... Ciò aumenta il requisito per la deframmentazione / reindicizzazione regolare dell'indice quando vengono aggiunte nuove righe.


La funzione newsequentialid () di SQL Server risolve il problema della frammentazione dell'indice dei GUID (sebbene 24 byte siano ancora un po 'eccessivi se non è assolutamente necessaria l'unicità globale). Vedi msdn.microsoft.com/en-us/library/ms189786.aspx.
ErikE

oops, volevo dire 16 byte.
ErikE

8

Una cosa che non dovresti mai fare è usare una chiave intelligente. Questa è una chiave in cui le informazioni sul record sono codificate nella chiave stessa e alla fine ti morderanno.

Ho lavorato in un posto, dove la chiave primaria era l'ID account, che era una combinazione di lettere e numeri. Non ricordo alcun dettaglio, ma, ad esempio, quegli account che erano di un certo tipo sarebbero stati nell'intervallo 600 e di un altro tipo, iniziavano con 400. È stato fantastico, fino a quando quel cliente ha deciso di chiedere entrambi tipi di lavoro. O ha cambiato il tipo di lavoro che hanno svolto.

Un altro luogo, ha utilizzato la posizione nella struttura ad albero come chiave primaria per i record. Quindi ci sarebbero record come il seguente.

Cat1.subcatA.record1
Cat1.subcatA.record2
Cat1.subcatB.record1
Cat2.subcatA.record1

Ovviamente, la prima cosa che i clienti volevano era un modo per spostare gli oggetti dall'albero. L'intero set di software è morto prima che accadesse.

Per favore, per favore, per favore, se stai scrivendo codice che dovrò mantenere, per favore non usare una chiave intelligente!


Sono d'accordo di tutto cuore. Smartkeys = stupido.
Robert C. Barth

2
Ciò non significa che le chiavi naturali siano stupide. Ma buon punto.

4

Sono un fan dell'incremento automatico come chiave primaria. So nel profondo del mio cuore che questa è una scappatoia, ma rende così facile ordinare i dati in base a quando sono stati aggiunti (ORDER BY ID DESC, per esempio).

3 colonne sembrano terribilmente difficili da analizzare umanamente.

E questo è il compromesso: di quanta capacità relazionale hai bisogno, rispetto a rendere QUESTA TABELLA DESTRA QUI comprensibile a un essere umano che la interroga (rispetto alla procedura memorizzata o all'interfaccia programmatica).

l'autoincremento è per noi umani. :-(


4

In generale, dipende.

Personalmente, mi piacciono gli int di autoincremento.

Ma una cosa che posso dirti è di non fidarti mai dei dati di altre fonti come chiave. Lo giuro, ogni volta che l'ho fatto torna a mordermi. Ebbene, mai più!


3

Dovrebbero esserci almeno 3 colonne che compongono la chiave primaria.

Non lo capisco.

Stai parlando di una "chiave naturale", ad esempio "nome e data di nascita"? Una chiave naturale potrebbe essere l'ideale se esiste, ma la maggior parte dei candidati per una chiave naturale non sono univoci (diverse persone con lo stesso nome) o non costanti (qualcuno può cambiare il proprio nome).

Int / BigInt quali autoincrement sono chiavi primarie abbastanza buone.

Preferisco Guid. Un potenziale problema con l'autoincrement è che il valore (es. "ID ordine") è assegnato dall'istanza del database (es. Dal "database delle vendite") ... che non funzionerà del tutto (invece inizi ad avere bisogno di chiavi composte) se hai mai bisogno di unire i dati creati da più di un'istanza di database (ad esempio da diversi uffici di vendita ciascuno con il proprio database).


Le chiavi primarie devono essere univoche, ma non è necessario che siano costanti. Quindi chiavi esterne dichiarate con "ON UPDATE CASCADE". Ma supporre che le chiavi primarie siano costanti aiuta a semplificare molte applicazioni. Questo è uno dei vantaggi delle chiavi surrogate.
Bill Karwin

3

RE GUID's

Fai attenzione se questo sarà un database davvero VERAMENTE VERAMENTE DAVVERO grande, molto carico e accesso veloce.

Nel mio ultimo lavoro, dove avevamo database da 100 a 500 milioni di record, i nostri addetti ai database si sono opposti con forza ai GUID e per un numero decimale di dimensioni adeguate. Hanno ritenuto che (sotto Oracle) la differenza di dimensioni nella memoria interna per una stringa Guid - rispetto a un valore decimale avrebbe fatto una differenza molto evidente nelle ricerche. (Chiavi più grandi = alberi più profondi da attraversare)

La natura casuale dei GUID riduce inoltre in modo significativo il fattore di riempimento per le pagine di indice, aumentando notevolmente la lacerazione e l'I / O del disco.


"Riduce il fattore di riempimento"? Non sono sicuro di cosa possa significare Fill-factor è un affare unico, definito come la percentuale di spazio libero richiesta a livello foglia dell'indice al momento della creazione dell'indice. Valori GUID in base alla loro distribuzione di natura casuale attraverso l'ampiezza del livello foglia sugli inserti in quello spazio libero fornito dal fattore di riempimento.
Ralph Shillington

1
Da quando un GUID è una stringa? I GUID dovrebbero essere archiviati internamente come 16 byte da qualsiasi DBMS rispettabile. Memorizzare come 32 byte nella rappresentazione esadecimale sarebbe inconcepibile! (o 36 con trattini o 38 con parentesi graffe)
ErikE

2

Colonne di incremento automatico. Sono in grado di far funzionare il mio codice perfettamente con SQL Server o Oracle, uno utilizzando l'identità e l'altro utilizzando sequenze tramite il mio DAL, e non potrei essere più felice. Sono d'accordo, i GUID a volte sono necessari se si esegue la replica o si inviano dati per riceverli in un secondo momento dopo l'elaborazione.


2

Ho sempre usato una chiave surrogata, un numero intero autoincrementante chiamato "id". Vedo molte ragioni per farlo anche quando un'altra opzione è ovvia:

  • Consistenza
  • Indipendente dai dati (unico, non distrutto dalle modifiche al formato)
  • Leggibile dagli umani

... e nessun motivo ragionevole per non:

  • Ambiguità nelle join? - L'aliasing delle tabelle è una pratica migliore, IMHO
  • Tavoli ottimali? - La rimozione di un byte per voce è un'ottimizzazione prematura, IMHO
  • Decisione per tavolo? - Non più coerente
  • Problemi di ridimensionamento? - Eh? Perché?
  • Struttura dati gerarchica? - Questo è denormalizzare, un altro argomento religioso. Basti dire che sono un fan in alcune circostanze in teoria, ma mai in pratica :)

ragioni sensate contro cui non ho ancora pensato o incontrato sono sempre benvenute ...


1

Questo è un classico "dipende". Non esiste una risposta giusta per ogni progetto. Mi piacciono cose diverse per situazioni diverse. Dipende se utilizzo un ORM e da cosa supporta. Dipende dall'architettura complessiva (distribuita o meno, ecc.). Scegline uno che pensi possa funzionare e passa a discutere su tabulazioni e spazi.


Desidera ancora sapere COME dipende; solo con consapevolezza di questi si può arrivare a fidarsi di se stessi per scegliere ...
Nicholas Leonard

1

Tendo a utilizzare l'opzione n. 1 o n. 3 a seconda delle dimensioni, del numero di persone che si connettono e se si tratta di una situazione di server di database multipli o meno.

L'opzione n. 2 non ha molto senso per me. Se uno qualsiasi dei tre non è sufficiente per identificare un record univoco, è possibile (senza passare attraverso macchinazioni extra) due hanno due record visualizzati con gli stessi valori in tutte e tre le colonne. Se vuoi imporre l'unicità su qualsiasi combinazione dei tre, aggiungi semplicemente un indice per loro.


1

Ho usato solo un int auto-incremento o un GUID. Il 99% delle volte ho usato auto-increment int. È proprio quello che mi è stato insegnato a usare quando ho appreso per la prima volta dei database e non ho mai incontrato un motivo per non usarli (anche se conosco i motivi per cui un GUID sarebbe migliore).

Mi piacciono gli int di incremento automatico perché aiuta con la leggibilità. Per esempio posso dire "dai un'occhiata al record 129383" ed è abbastanza facile per qualcuno entrare e trovarlo. Con un GUID che è quasi impossibile da fare.


2
Perché dici questo? Sembra che molte persone utilizzino un numero intero con incremento automatico. Non può essere così male se funziona e funziona bene per ciò di cui hai bisogno.
dtc

1

Dopo una risposta di definizione di base, cosa costituisce un file buona chiave primaria è lasciato in gran parte alla religione e agli argomenti della sala relax. Se hai qualcosa che è e sarà sempre mappato in modo univoco a una singola riga, allora funzionerà bene come chiave primaria. Oltre quel punto, ci sono altre considerazioni:

  • La definizione della chiave primaria non è eccessivamente complessa? Evita di introdurre complessità inutili per il bene di seguire una "best practice"?
  • Esiste una chiave primaria migliore possibile che richiederebbe meno overhead per la gestione del database (ad es. INTEGER vs. VARCHAR, ecc.)?
  • Sono ASSOLUTAMENTE certo che l'unicità e la definizione invariante della mia chiave primaria non cambierà?

Quest'ultimo è probabilmente ciò che spinge la maggior parte delle persone a usare cose come GUID o colonne intere autoincrementanti, perché fare affidamento su cose come indirizzi, numeri di telefono, nome / cognome, ecc., Non tagliarlo. L'unica invariante sulle persone a cui riesco a pensare sono i SSN, ma non sono nemmeno sicuro al 100% che quelli rimangano per sempre unici.

Si spera che questo aiuti ad aggiungere un po 'di chiarezza ...


Ci sono alcuni casi storici in cui i SSN non sono unici.
Bill Karwin

1

Il modo in cui mi avvicino alle chiavi primarie (e ritengo sia il migliore) è evitare di avere un approccio "predefinito". Ciò significa che invece di semplicemente schiaffeggiare un numero intero autoincrementante e chiamarlo un giorno, guardo il problema e dico "c'è una colonna o un gruppo di colonne che sarà sempre unqiue e non cambierà?" Se la risposta è sì, adotto questo approccio.


Significa che "eviti l'incremento automatico degli interi ogni volta che puoi"? A quanto mi risultava, gli esperti del settore ritenevano che le migliori prestazioni su database su larga scala derivassero da PK a colonna singola indicizzati, con firma minima e incrementali.
Hardryv

1
Ho sempre pensato che gli esperti usassero lo strumento migliore per il lavoro
Andrew G. Johnson,

1

Quasi sempre numeri interi.

Hanno altri buoni motivi oltre ad essere più piccoli / più veloci da elaborare. Quale preferiresti scrivere - "404040" o "3463b5a2-a02b-4fd4-aa0f-1d3c0450026c"?


Quest'ultimo può essere un numero intero, con l'aggiunta di trattini e in base 16. Ma sì, 404040 è più veloce da elaborare rispetto al lungo GUID. Inoltre, 0 è ancora più veloce da elaborare perché non richiede un singolo bit di dati!
strager

1

Solo leggermente rilevante, ma una cosa che ho iniziato a fare di recente quando ho piccole tabelle di classificazione (essenzialmente quelle che rappresenterebbero ENUM nel codice) è che renderò la chiave primaria char (3) o char (4). Quindi creo quelle chiavi primarie rappresentative del valore di ricerca.

Ad esempio, ho un sistema di preventivi per i nostri agenti di vendita interni. Abbiamo "categorie di costo" a cui viene assegnata una delle voci della riga di preventivo ... Quindi ho una tabella di ricerca del tipo chiamata "tCostCategories", dove la chiave primaria è "MTL", "SVC", "TRV", "TAX", "ODC". Altre colonne nella tabella di ricerca memorizzano maggiori dettagli, come il normale significato inglese dei codici, "Materiale", "Servizio", "Viaggio", "Tasse", "Altri costi diretti" e così via.

Questo è davvero bello perché non usa più spazio di un int, e quando guardi i dati di origine, non devi collegare la tabella di ricerca per sapere qual è il valore. Ad esempio, una riga di virgolette potrebbe essere simile a:

1 PartNumber $ 40 MTL
2 AltroPartNumber $ 29,99 SVC
3 PartNumber2 $ 150 TRV

È molto più semplice usare un int per rappresentare le categorie e quindi collegare 1, 2, 3 su tutte le linee: hai i dati proprio davanti a te e le prestazioni non sembrano affatto influenzate (non che io ' ho veramente provato.)

Per quanto riguarda la vera domanda ... mi piacciono gli identificatori unici RowGUID. Non sono al 100% su questo, ma non tutte le righe hanno comunque RowGuid interno ?? In tal caso, l'utilizzo di RowGuid richiederebbe effettivamente meno spazio degli int (o qualsiasi altra cosa per quella materia). Tutto quello che so è che se è abbastanza buono per M $ da usare in GreatPlains, allora è abbastanza buono per me. (Dovrei abbassarmi ??)


1

Oh, un altro motivo per cui uso i GUID: utilizzo una struttura dati gerarchica. Cioè, ho una tabella "Azienda" e una tabella "Fornitore" per le quali le chiavi primarie corrispondono. Ma ho anche una tabella "Manufacturer" che "eredita" anche da Company. I campi comuni a Fornitori e Produttori non vengono visualizzati in queste tabelle, ma in Azienda. In questa configurazione, l'uso di int è molto più doloroso di Guids. Come minimo, non puoi usare le chiavi primarie di identità.


1
Sì, puoi, semplicemente non fai in modo che le tabelle dei sottotipi abbiano la proprietà identity, invece ottengono inserimenti espliciti del valore della tabella del supertipo. Si prega di consultare stackoverflow.com/questions/2112882/...
Erike

1

Mi piacciono le chiavi naturali, ogni volta che posso fidarmi di loro. Sono disposto a pagare un piccolo prezzo in termini di prestazioni per utilizzare chiavi che abbiano senso per gli esperti in materia.

Per le tabelle che descrivono le entità, dovrebbe esserci una semplice chiave naturale che identifichi le singole istanze nello stesso modo in cui fanno le persone dell'oggetto. Se l'oggetto non ha identificatori affidabili per una delle entità, ricorrerò a una chiave surrogata.

Per le tabelle che descrivono le relazioni, utilizzo una chiave composta, in cui ogni componente fa riferimento a un'entità che partecipa alla relazione e quindi una riga in una tabella di entità. Anche in questo caso, il calo delle prestazioni per l'utilizzo di una chiave composta è generalmente minimo.

Come altri hanno sottolineato, il termine "chiave primaria" è un po 'fuorviante. Nel modello di dati relazionali, il termine utilizzato è "chiavi candidate". Potrebbero esserci diverse chiavi candidate per una singola tabella. Logicamente, ognuno è buono come l'altro. Scegliere uno di loro come "primario" e fare tutti i riferimenti tramite quella chiave è semplicemente una scelta che il designer può fare.


Descrivi alcuni esempi di chiavi naturali affidabili?
ErikE

1
"affidabile" non è una proprietà di una chiave di per sé. Piuttosto, ha a che fare con la chiave nel contesto delle persone che forniscono i dati. Se stai scrivendo un'app da vendere a qualcuno che gestirà effettivamente i dati, devi indovinare quali chiavi saranno affidabili o meno per il cliente. Data la varietà di clienti, quasi sicuramente indovinerai qualcosa di sbagliato per una frazione della tua clientela.
Walter Mitty

Detto quanto sopra, ecco un esempio di una chiave di cui ci fidavamo molto tempo fa. Avevamo un database sui corsi. Comprendeva libri di testo e altro materiale per corsi su corsi, offerte di corsi programmati, istruttori qualificati per insegnare corsi, prerequisiti del corso, lezioni e così via. Quando lo sviluppo del corso creava un nuovo corso, una delle prime cose che facevano era assegnare un codice del corso. Erano responsabili di assicurarsi che i codici dei corsi fossero univoci e che i corsi non cambiassero mai il loro codice, una volta assegnati. Faceva parte dei dati che ci venivano forniti.
Walter Mitty

Un altro buon esempio di chiave naturale attendibile è VIN (Vehicle Identification Number). Negli ultimi anni, ogni veicolo venduto come nuovo ha un VIN collegato. Ci si può fidare di essere unici e immutabili.
Walter Mitty

1

Guids.period.

Nel caso in cui sia necessario scalare o assegnare la chiave primaria in modo alternativo, saranno tuoi amici. Puoi aggiungere indici per tutto il resto.


aggiornamento per chiarire la mia dichiarazione.

Ho lavorato su molti tipi diversi di siti. Dalle piccole offerte per server singolo a quelle di grandi dimensioni supportate da più DB e server web. Ci sono state sicuramente app che sarebbero andate bene con l'incremento automatico degli int come chiavi primarie. Tuttavia, quelli non si adattano al modello di come faccio le cose.

Quando si utilizza un GUID è possibile generare l'ID ovunque. Potrebbe essere generato da un server remoto, dalla tua app web, all'interno del database stesso o anche all'interno di più database in una situazione multimaster.

D'altra parte, un INT auto incrementato può essere generato in modo sicuro solo all'interno del database primario. Di nuovo, questo potrebbe andare bene se hai un'applicazione che sarà intimamente legata a quel server DB di supporto e la scalabilità orizzontale non è qualcosa di cui sei interessato.

Certo, l'utilizzo di GUID significa che devi avere processi di reindicizzazione notturni. Tuttavia, se stai usando qualcosa di diverso da un INT auto incrementato dovresti farlo comunque. Diamine, anche con un INT come primario è probabile che tu abbia altri indici che devono essere rigenerati per affrontare la frammentazione. Pertanto, l'utilizzo dei GUID non aggiunge esattamente un altro problema perché tali attività devono essere eseguite a prescindere.

Se dai un'occhiata alle app più grandi là fuori, noterai qualcosa di importante: tutte usano GUID codificati Base64 come chiavi. Il motivo è semplice, l'utilizzo dei GUID ti consente di scalare fuori facilmente considerando che non può essere un sacco di cerchi per saltare attraverso quando si tenta di scalare fuori INT.

La nostra ultima app attraversa un periodo di inserimenti pesanti che dura circa un mese. Dopodiché, il 90 +% delle query viene selezionato per il rapporto. Per aumentare la capacità posso attivare server DB aggiuntivi durante questo periodo di inserimento di grandi dimensioni; e successivamente unirli facilmente in un unico DB per i rapporti. Tentare di farlo con gli INT sarebbe un incubo assoluto.

Francamente, ogni volta che si raggruppa un database o si imposta la replica, il server DB richiederà comunque di avere GUID sulla tabella. Quindi, se pensi che il tuo sistema potrebbe aver bisogno di crescere, scegli quello che è buono.


Hai mai esaminato il fattore di riempimento dei tuoi indici? La natura casuale del GUID produce formaggio svizzero - riducendo drasticamente la loro efficacia.
stephbu

2
"Guids.period": è così sbagliato. I GUID dovrebbero essere usati dove appropriato. Come ha sottolineato l'altro commentatore, potrebbe semplificare la vita come programmatore, ma influisce sulle dimensioni e sulle prestazioni complessive del DB.
Mitch Wheat

Alla fine della giornata, posso scalare le mie app su più server di database senza problemi. Ma immagino che voi ragazzi lavoriate su piccoli siti.
NotMe

3
GUID potrebbe essere ok per la chiave primaria logica, ma MAI MAI MAI usare una colonna GUID come chiave di CLUSTERING - annegherai nella frammentazione dell'indice che porta a prestazioni
SCARSE

Certamente non proclamerei "Guids.period". su questo argomento - in effetti anche in un settore così pieno zeppo di "migliori pratiche" quel tipo di affermazione ti mette su un terreno instabile per impostazione predefinita (in particolare con quella dichiarazione). Qualcosa di così doloroso da affrontare come un GUID necessita di una dura giustificazione e, come dice JL, penso che la maggior parte di noi lo considererebbe l'ultima risorsa. È come se avessi postato senza leggere il resto del thread.
Hardryv

0

Questo è un argomento complesso, che tu te ne renda conto o no. Potrebbe rientrare nella sezione di questa FAQ su StackOverflow.

Che tipo di domande non dovrei fare qui?

Evita di fare domande soggettive, argomentative o che richiedono discussioni approfondite. Questo è un posto per domande a cui è possibile rispondere!

Questo è stato dibattuto per anni e continuerà a essere discusso per anni. L'unico indizio di consenso che ho visto è che le risposte sono in qualche modo prevedibili a seconda che tu stia chiedendo a un ragazzo OO (i GUID sono l'unica strada da percorrere!), Un modellatore di dati (le chiavi naturali sono l'unico modo per andare!), o un DBA orientato alle prestazioni (gli INT sono l'unica strada da percorrere!).


Non lascerò che la discussione si prolunghi. Ero solo curioso di vedere il consenso generale.
Perpetualcoder

1
Dico di fare tutte le domande che desideri! Altrimenti, questa comunità diventerà statica e ipercontrollata come sembra essere diventata wikipedia. Mi sembra che alcune volte sia necessario lasciare che le persone chiedano qualunque cosa scelgano di chiedere. Fidati di loro e potrebbero arrivare a fidarsi di se stessi!
Nicholas Leonard
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.