Qual è la procedura ottimale per le chiavi primarie nelle tabelle?


256

Durante la progettazione di tabelle, ho sviluppato l'abitudine di avere una colonna unica e che creo la chiave primaria. Ciò si ottiene in tre modi a seconda delle esigenze:

  1. Colonna intera identità che aumenta automaticamente.
  2. Identificatore univoco (GUID)
  3. Una colonna carattere corto (x) o intero (o altro tipo numerico relativamente piccolo) che può fungere da colonna identificatore di riga

Il numero 3 verrebbe utilizzato per una ricerca abbastanza piccola, per lo più leggi le tabelle che potrebbero avere un codice stringa di lunghezza statica univoco o un valore numerico come un anno o un altro numero.

Per la maggior parte, tutte le altre tabelle avranno un numero intero auto-incrementante o una chiave primaria identificativa univoca.

La domanda :-)

Di recente ho iniziato a lavorare con database che non hanno un identificatore di riga coerente e le chiavi primarie sono attualmente raggruppate in varie colonne. Qualche esempio:

  • datetime / personaggio
  • datetime / integer
  • datetime / varchar
  • car / nvarchar / nvarchar

C'è un caso valido per questo? Avrei sempre definito un'identità o una colonna identificatore univoco per questi casi.

Inoltre ci sono molte tabelle senza chiavi primarie. Quali sono i motivi validi, se presenti, per questo?

Sto cercando di capire perché i tavoli sono stati progettati così come sono, e sembra essere un gran casino per me, ma forse ci sono state buone ragioni per farlo.

Una terza domanda per aiutarmi a decifrare le risposte: nei casi in cui vengono utilizzate più colonne per comprendere la chiave primaria composta, esiste un vantaggio specifico per questo metodo rispetto a una chiave surrogata / artificiale? Sto pensando principalmente alle prestazioni, alla manutenzione, all'amministrazione, ecc.?


Ho trovato le competenze del database: un approccio sano alla scelta delle chiavi primarie per essere una buona lettura e seguo la maggior parte dei punti delineati.
user2864740

Risposte:


254

Seguo alcune regole:

  1. Le chiavi primarie devono essere piccole quanto necessario. Preferisci un tipo numerico perché i tipi numerici sono memorizzati in un formato molto più compatto rispetto ai formati dei caratteri. Questo perché la maggior parte delle chiavi primarie saranno chiavi esterne in un'altra tabella e verranno utilizzate in più indici. Più piccola è la chiave, più piccolo è l'indice, meno pagine verranno utilizzate nella cache.
  2. Le chiavi primarie non dovrebbero mai cambiare. L'aggiornamento di una chiave primaria dovrebbe essere sempre fuori discussione. Questo perché è molto probabile che venga utilizzato in più indici e utilizzato come chiave esterna. L'aggiornamento di una singola chiave primaria potrebbe causare l'effetto a catena delle modifiche.
  3. NON utilizzare "chiave primaria del problema" come chiave primaria del modello logico. Ad esempio il numero di passaporto, il numero di previdenza sociale o il numero del contratto di lavoro poiché queste "chiavi primarie" possono cambiare in situazioni reali.

Su surrogato vs chiave naturale, mi riferisco alle regole sopra. Se la chiave naturale è piccola e non cambierà mai, può essere utilizzata come chiave primaria. Se la chiave naturale è grande o può cambiare, uso le chiavi surrogate. Se non esiste una chiave primaria, creo comunque una chiave surrogata perché l'esperienza mostra che aggiungerai sempre tabelle al tuo schema e vorrei che avessi messo in atto una chiave primaria.


3
Mi piace! Hai della documentazione per la base delle tue "regole"? Grazie!
Lloyd Cotten,

4
No, solo esperienza. Quando si ha a che fare con database "piccoli" questa roba non ha molta importanza. Ma quando hai a che fare con un grande db, tutte le piccole cose contano. Immagina se hai 1 miliardo di righe con int o long pk's rispetto all'utilizzo di text o guid's. C'è un'enorme differenza!
Logicalmind,

44
Ricorda solo di mettere quell'indice univoco sulla chiave naturale (se ne esiste effettivamente una, che spesso non è il caso) quando usi una chiave artificiale.
HLGEM,

3
@Lloyd Cotten: ecco cosa dice un fornitore di big data engine a supporto della regola numero 1: skyfoundry.com/forum/topic/24 . E mi ha convinto a tornare a Ints
piani di cottura

4
anche se "sai" che "la chiave naturale è piccola e non cambierà mai", pensaci due volte. "Non riutilizziamo mai quei codici" sono le ultime parole famose .... Circa le uniche cose che rientrano nelle categorie di piccoli, che non cambiano mai sono iso e altri standard (codici paese, codici aeroporto iata,). Cose come "qual è la rappresentazione di 2 lettere per questo marchio interno" ... pensaci due volte prima di assumere che "esso" non cambierà mai, sei una decisione finanziaria lontana da una ricostruzione del database.
Andrew Hill,

90

Le chiavi artificiali dei versi naturali sono una sorta di dibattito religioso all'interno della comunità del database - vedi questo articolo e altri a cui si collega. Non sono a favore di avere sempre chiavi artificiali, né di non averle mai . Deciderei caso per caso, ad esempio:

  • Stati Uniti: sceglierei state_code ('TX' per il Texas ecc.), Piuttosto che state_id = 1 per il Texas
  • Dipendenti: di solito creo un ID_impiegato artificiale, perché è difficile trovare qualcos'altro che funzioni. SSN o equivalente potrebbe funzionare, ma potrebbero esserci problemi come un nuovo falegname che non ha ancora fornito il suo SSN.
  • Cronologia salariale dei dipendenti: (employee_id, start_date). Vorrei non creare un employee_salary_history_id artificiale. A che punto servirebbe (a parte la "coerenza insensata" )

Ovunque vengano utilizzate le chiavi artificiali, è sempre necessario dichiarare vincoli univoci sulle chiavi naturali. Ad esempio, utilizzare state_id se è necessario, ma è meglio dichiarare un vincolo univoco su state_code, altrimenti si finirà sicuramente con:

state_id    state_code   state_name
137         TX           Texas
...         ...          ...
249         TX           Texas

9
In alcuni casi con SQL Server 2005/2008 la chiave naturale (di testo) può essere più veloce di una chiave int. Ho un'app con un codice amichevole di 7-8 caratteri che usiamo come chiave primaria e che è stata più veloce (e spesso più conveniente) di un surrogato int. Avevamo comunque bisogno del codice in modo da poter disporre di un codice leggibile / memorabile umano che potessimo trasferire in modo sicuro senza conflitti a un'istanza dell'applicazione diversa (più siti che si aggregano in un sito più grande).
lambacck,

1
+1 Buona risposta. Tuttavia, vorrei che l'agente del personale fosse la fonte attendibile dell'identificatore di un dipendente, vale a dire l'agente responsabile della verifica dei dipendenti nella vita reale che potrebbero utilizzare identificatori come SSN, acquisire referenze, ecc. Il reparto personale deve essere attendibile fonte di identificatori dei dipendenti, non DBMS!
giorno

@ onedaywhen- Intnt. fidarsi dell'ufficiale del personale. Le persone se ne vanno, ne arrivano di nuove e hanno idee diverse. Fornire loro l'accesso all'identificatore che ritengono unico / che desiderano utilizzare, ma internamente per il db, dba dovrebbe prendere la propria decisione
Dave Pile

1
Si noti che il SSN non è necessariamente unico in tutti i paesi. Almeno in Austria, più persone potrebbero condividere lo stesso numero
maja,

Anche in alcuni paesi (penso anche negli Stati Uniti) in realtà raccomandano di non condividere il SSN.
Stijn de Witt,

25

Solo un commento in più su qualcosa che viene spesso trascurato. A volte il mancato utilizzo di una chiave surrogata presenta vantaggi nelle tabelle figlio. Diciamo che abbiamo un design che ti consente di eseguire più aziende all'interno di un unico database (forse è una soluzione ospitata o qualsiasi altra cosa).

Diciamo che abbiamo queste tabelle e colonne:

Company:
  CompanyId   (primary key)

CostCenter:
  CompanyId   (primary key, foreign key to Company)
  CostCentre  (primary key)

CostElement
  CompanyId   (primary key, foreign key to Company)
  CostElement (primary key)

Invoice:
  InvoiceId    (primary key)
  CompanyId    (primary key, in foreign key to CostCentre, in foreign key to CostElement)
  CostCentre   (in foreign key to CostCentre)
  CostElement  (in foreign key to CostElement)

Nel caso in cui l'ultimo bit non abbia senso, Invoice.CompanyIdfa parte di due chiavi esterne, una alla tabella CostCentre e una alla tabella CostElement . La chiave primaria è ( InvoiceId , CompanyId ).

In questo modello, non è possibile rovinare e fare riferimento a un CostElement di una società e un CostCentre di un'altra società. Se una chiave surrogata fosse utilizzata nelle tabelle CostElement e CostCentre , lo sarebbe.

Meno possibilità di sbagliare, meglio è.


6
Questo è uno svantaggio sotto citato quando si usano le chiavi surrogate. Se la tabella ha una chiave surrogata, posso ancora usarla per questo tipo di vincoli. Sfortunatamente sebbene il vincolo richieda un indice ed è strano creare un indice univoco su (surrogate_key, other_column) quando (surrogate_key) è unico da solo. Inoltre, (other_column) è spesso totalmente ridondante in una tabella della mappa poiché (surrogate_key) è unica in quella straniera. I surrogati possono davvero rovinare le cose.
Samuel Danielson,

24

Evito di usare le chiavi naturali per una semplice ragione: l'errore umano. Sebbene gli identificatori univoci naturali siano spesso disponibili (SSN, VIN, numero di conto, ecc.), Richiedono che un umano li inserisca correttamente. Se stai utilizzando SSN come chiave primaria, qualcuno traspone un paio di numeri durante l'immissione dei dati e l'errore non viene rilevato immediatamente, quindi devi affrontare la modifica della chiave primaria.

Le mie chiavi primarie sono tutte gestite dal programma di database in background e l'utente non ne è mai a conoscenza.


1
Ho lavorato con alcuni database che utilizzavano SSN o ID fiscali come chiavi primarie. Inefficiente quando si tratta di archiviazione e riferimenti a chiave esterna. Per non parlare del fatto che l'SSN di una persona può cambiare. Quindi sono completamente d'accordo con te.
Alex Jorgenson,

13

Non c'è alcun problema nel creare la chiave primaria da vari campi, questa è una chiave naturale .

È possibile utilizzare una colonna Identity (associata a un indice univoco nei campi candidati) per creare una chiave surrogata .

Questa è una vecchia discussione. Preferisco le chiavi surrogate nella maggior parte delle situazioni.

Ma non ci sono scuse per la mancanza di una chiave.

RE: EDIT

Sì, ci sono molte controversie al riguardo: D

Non vedo alcun evidente vantaggio sui tasti naturali, oltre al fatto che sono la scelta naturale. Penserai sempre a Nome, Numero sociale - o qualcosa del genere - invece di idPerson .

Le chiavi surrogate sono la risposta ad alcuni dei problemi che hanno le chiavi naturali (propagando le modifiche per esempio).

Quando ti abitui ai surrogati, sembra più pulito e gestibile.

Ma alla fine, scoprirai che è solo una questione di gusti - o mentalità -. Le persone "pensano meglio" con le chiavi naturali, e gli altri no.


13
Le persone "pensano meglio" con chiavi naturali. Macchine e database, no.
FDCastel,

11

Le tabelle dovrebbero avere sempre una chiave primaria. In caso contrario, avrebbe dovuto essere un campo AutoIncrement.

A volte le persone omettono la chiave primaria perché trasferiscono molti dati e potrebbe rallentare (dipende dal database) il processo. MA, dovrebbe essere aggiunto dopo di esso.

Qualche commento sulla tabella dei collegamenti , questo è giusto, è un'eccezione MA i campi dovrebbero essere FK per mantenere l'integrità, ed è in alcuni casi quei campi possono essere anche chiavi primarie se il duplicato nei collegamenti non è autorizzato ... ma da conservare in un forma semplice perché l'eccezione è qualcosa di frequente nella programmazione, la chiave primaria dovrebbe essere presente per mantenere l'integrità dei dati.


Sono d'accordo. E nel caso in cui si debbano inserire molti dati, rimuovere il vincolo della chiave primaria (o utilizzare INSERT IDENTITY ON in TSQL) e rimetterlo in seguito :)
Andrew Rollings,

1
Ci sono eccezioni: le tabelle dei collegamenti ovviamente
annakata,

Un altro motivo: se non esiste una chiave PK / unica, i browser delle tabelle (intendo qualcosa come Access / SQL Server Management Studio) si rifiuteranno di aggiornare / eliminare una singola riga con una riga duplicata. Dovrai scrivere SQL per questo.
Dennis C,

È abbastanza comune omettere un PK da una tabella dei fatti del data warehouse. In Oracle puoi fare riferimento alla pseudocolonna ROWID come identificatore univoco a breve termine (ad es. Non archiviarlo da qualche parte e aspettarti che non cambi)
David Aldridge,

9

Oltre a tutte quelle buone risposte, voglio solo condividere un buon articolo che ho appena letto, Il grande dibattito sulle chiavi primarie .

Solo per citare alcuni punti:

Lo sviluppatore deve applicare alcune regole quando sceglie una chiave primaria per ogni tabella:

  • La chiave primaria deve identificare in modo univoco ciascun record.
  • Il valore della chiave primaria di un record non può essere nullo.
  • Il valore-chiave principale deve esistere quando viene creato il record.
  • La chiave primaria deve rimanere stabile: non è possibile modificare i campi della chiave primaria.
  • La chiave primaria deve essere compatta e contenere il minor numero possibile di attributi.
  • Il valore della chiave primaria non può essere modificato.

Le chiavi naturali (tendono a) infrangere le regole. Le chiavi surrogate sono conformi alle regole. (Faresti meglio a leggere quell'articolo, vale la pena!)


7

Cosa c'è di speciale nella chiave primaria?

Qual è lo scopo di una tabella in uno schema? Qual è lo scopo di una chiave di una tabella? Cosa c'è di speciale nella chiave primaria? Le discussioni sulle chiavi primarie sembrano mancare al punto in cui la chiave primaria fa parte di una tabella e quella tabella fa parte di uno schema. Ciò che è meglio per le relazioni tra tabelle e tabelle dovrebbe guidare la chiave utilizzata.

Le tabelle (e le relazioni tra tabelle) contengono informazioni sulle informazioni che si desidera registrare. Questi fatti dovrebbero essere autonomi, significativi, facilmente comprensibili e non contraddittori. Dal punto di vista del design, le altre tabelle aggiunte o rimosse da uno schema non dovrebbero influire sulla tabella in questione. Deve esserci uno scopo per la memorizzazione dei dati relativi solo alle informazioni stesse. Comprendere ciò che è memorizzato in una tabella non dovrebbe richiedere di sottoporsi a un progetto di ricerca scientifica. Nessun fatto memorizzato per lo stesso scopo deve essere archiviato più di una volta. Le chiavi sono una parte o una parte delle informazioni che vengono registrate, che è unica e la chiave primaria è la chiave appositamente designata che deve essere il punto di accesso principale alla tabella (cioè dovrebbe essere scelta per coerenza e utilizzo dei dati, non solo inserire prestazione).

  • A parte: purtroppo l'effetto collaterale della maggior parte dei database progettati e sviluppati dai programmatori di applicazioni (cosa che a volte sono) è che ciò che è meglio per l'applicazione o il framework dell'applicazione spesso guida la scelta della chiave primaria per le tabelle. Questo porta a chiavi integer e GUID (poiché sono semplici da usare per i framework applicativi) e ai disegni monolitici delle tabelle (in quanto riducono il numero di oggetti del framework applicativo necessari per rappresentare i dati in memoria). Queste decisioni di progettazione del database basate sull'applicazione portano a problemi significativi di coerenza dei dati se utilizzati su larga scala. I framework applicativi progettati in questo modo portano naturalmente alla progettazione di tabelle alla volta. I "record parziali" vengono creati in tabelle e dati compilati nel tempo. L'interazione su più tabelle viene evitata o quando utilizzata provoca dati incoerenti quando l'applicazione funziona in modo errato. Questi progetti portano a dati privi di significato (o difficili da comprendere), a dati distribuiti su tabelle (è necessario guardare altre tabelle per dare un senso alla tabella corrente) e dati duplicati.

Si diceva che le chiavi primarie dovessero essere piccole quanto necessario. Direi che le chiavi dovrebbero essere grandi quanto basta. È necessario evitare l'aggiunta casuale di campi senza significato a una tabella. È anche peggio ricavare una chiave da un campo insignificante aggiunto casualmente, specialmente quando distrugge la dipendenza di join da un'altra tabella alla chiave non primaria. Questo è ragionevole solo se non ci sono buone chiavi candidate nella tabella, ma questa occorrenza è sicuramente un segno di una cattiva progettazione dello schema se usata per tutte le tabelle.

È stato anche detto che le chiavi primarie non dovrebbero mai cambiare poiché l'aggiornamento di una chiave primaria dovrebbe sempre essere fuori questione. Ma l'aggiornamento è lo stesso di delete seguito da insert. In base a questa logica, non si dovrebbe mai eliminare un record da una tabella con una chiave e quindi aggiungere un altro record con una seconda chiave. L'aggiunta della chiave primaria surrogata non rimuove il fatto che l'altra chiave esista nella tabella. L'aggiornamento di una chiave non primaria di una tabella può distruggere il significato dei dati se altre tabelle hanno una dipendenza da tale significato tramite una chiave surrogata (ad esempio una tabella di stato con una chiave surrogata con la descrizione dello stato modificata da "Elaborato" a "Annullato 'corromperebbe sicuramente i dati). Ciò che dovrebbe essere sempre fuori discussione è la distruzione del significato dei dati.

Detto questo, sono grato per i molti database mal progettati che esistono oggi nelle aziende (insensati-surrogati-keyed-data-corrotti-1NF behemoths), perché ciò significa che c'è una quantità infinita di lavoro per le persone che capiscono la corretta progettazione del database . Ma sul lato triste, a volte mi fa sentire come Sisifo, ma scommetto che aveva un diavolo di un 401k (prima dell'incidente). Stare lontano da blog e siti Web per importanti domande sulla progettazione di database. Se si stanno progettando database, cercare CJ Date. Puoi anche fare riferimento a Celko per SQL Server, ma solo se tieni per primo il naso. Sul lato Oracle, fai riferimento a Tom Kyte.


1
"In base a questa logica, non si dovrebbe mai eliminare un record da una tabella con una chiave e quindi aggiungere un altro record con una seconda chiave." - C'è un caso per questo, ed è proprio quello che farà una clausola "ON DELETE RESTRICT" su una chiave esterna. In alcuni casi (diciamo dove è richiesta una pista di controllo), un campo booleano "eliminato" sarebbe meglio che consentire l'eliminazione del record.
Waz,

6

Una chiave naturale, se disponibile, è generalmente la migliore. Quindi, se datetime / char identifica in modo univoco la riga ed entrambe le parti sono significative per la riga, va benissimo.

Se solo il datetime è significativo, e il carattere è solo appiccicato per renderlo unico, allora potresti anche andare con un campo identificativo.


9
Di solito il migliore? Non ho alcuna base scientifica, ma sono quasi sicuro che la maggior parte delle persone preferisce una chiave surrogata rispetto a quella naturale. In molti casi non esiste una chiave naturale.
JC.

3
Dovrebbe esserci SEMPRE una chiave naturale per qualsiasi riga del database. Quella chiave "naturale" può essere qualcosa generata nel mondo degli affari o dal tuo sistema tecnico, ma dovrebbe sempre esistere.
Tom H,

2
Se, nel tuo mondo, è quello che è stato determinato come l'unico modo per identificare una riga nella tabella, allora sì. Naturalmente, quando un designer sceglie di creare un GUID per un PK, di solito è perché non ha fatto il lavoro per trovare la chiave naturale REALE, quindi in quel caso il GUID NON è la chiave naturale.
Tom H,

8
2. Se prendi la tua chiave dal mondo naturale, il mondo naturale cambierà per spezzare la chiave. Se usi il numero di telefono, otterrai due utenti della stessa famiglia. Se usi il cognome, si sposano. Se usi SSN, le leggi sulla privacy cambieranno e ti richiederanno di rimuoverle.
James Orr,

2
@ Barry: RE: # 2. se il mondo naturale cambia e ciò provoca il cambiamento della tua chiave naturale significa che hai fatto un cattivo lavoro selezionando una chiave naturale. Per definizione, una chiave naturale non cambia nel tempo.
Tom H,

6

Ecco la mia regola dei pollici su cui mi sono accontentato dopo oltre 25 anni di esperienza di sviluppo.

  • Tutte le tabelle dovrebbero avere una chiave primaria a colonna singola che incrementa automaticamente.
  • Includilo in qualsiasi vista destinata ad essere aggiornabile
  • La chiave primaria non dovrebbe avere alcun significato nel contesto dell'applicazione. Ciò significa che non dovrebbe essere uno SKU, un numero di conto o un ID dipendente o qualsiasi altra informazione significativa per la tua applicazione. È semplicemente una chiave univoca associata a un'entità.

La chiave primaria viene utilizzata dal database a fini di ottimizzazione e non deve essere utilizzata dall'applicazione per l'identificazione di una particolare entità o relativa a una determinata entità.

Avere sempre una chiave primaria a valore singolo rende l'esecuzione di UPSERT molto semplice.

Utilizzare indici aggiuntivi per supportare chiavi a più colonne che hanno un significato nell'applicazione.


5

Le chiavi naturali contro quelle artificiali per me sono una questione di quanta logica aziendale desideri nel tuo database. Il numero di previdenza sociale (SSN) è un ottimo esempio.

"Ogni client nel mio database avrà e dovrà avere un SSN." Bam, fatto, rendilo la chiave primaria e falla finita. Ricorda solo che quando la tua regola aziendale cambia, sei bruciato.

Non mi piacciono le chiavi naturali, a causa della mia esperienza con il cambiamento delle regole aziendali. Ma se sei sicuro che non cambierà, potrebbe impedire alcuni join critici.


8
E ho visto dati in cui SSN non è unico anche se dovrebbe essere. Fai molta attenzione alle chiavi naturali se importi i tuoi dati da un'altra fonte!
HLGEM,

2
Se sei soggetto a furto di identità, puoi cambiare il tuo numero di previdenza sociale. Ci sono altre quattro situazioni in cui cambieranno il tuo numero e saranno elencate sul sito ssa.gov.
Zvi Twersky,

4

Sospetto che per il progettista della struttura dati originale sia necessaria la terapia arrotolata per giornali di Steven A. Lowe.

A parte questo, i GUID come chiave primaria possono essere un maiale alle prestazioni. Non lo consiglierei.


2
Dire che è un maiale alle prestazioni è un'ottimizzazione prematura. In alcuni casi sono richieste guide (client disconnessi, unione futura di tabelle, replica)
JC.

2
"Ottimizzazione precoce" è una frase abusata di SO (IMHO)! Sì, i GUID possono essere richiesti in ALCUNI casi, ma Andrew ha ragione nel sottolineare che non dovrebbero essere usati come tipo di dati predefinito, sia che siano richiesti o meno.
Tony Andrews,

OK, in realtà non era un'ottimizzazione prematura. Quello che intendevo dire è che la maggior parte delle persone non sperimenta il volume richiesto per notare la differenza di prestazioni. Sì, usa l'autoincremento se sai che non avrai mai bisogno di una guida.
JC.

Oppure usa entrambi. Avere una chiave primaria basata su int / long per piacevoli selezioni e join rapidi, quindi un campo guida. Almeno, è quello che sto facendo. È sbagliato? Non dovrei farlo? :)
Andrew Rollings,

Sto anche usando entrambe le colonne. Ma non sono sicuro se sia sbagliato o no. Hai trovato @AndrewRollings?
YÒGÎ

3

È necessario utilizzare una chiave primaria "composita" o "composta" che comprende più campi.

Questa è una soluzione perfettamente accettabile, vai qui per maggiori informazioni :)


3

Anch'io uso sempre una colonna ID numerica. In Oracle uso il numero (18,0) per nessun motivo reale al di sopra del numero (12,0) (o qualunque sia un int piuttosto che un lungo), forse non voglio preoccuparmi di ottenere qualche miliardo di righe in il db!

Includo anche una colonna creata e modificata (tipo timestamp) per il tracciamento di base, dove sembra utile.

Non mi dispiace impostare vincoli univoci su altre combinazioni di colonne, ma mi piace molto il mio ID, creato, modificato i requisiti di base.


2
Devo anche sottolineare che non inserisco gli ID nelle tabelle link / join, ma solo nelle tabelle contenenti dati.
JeeBee,

3

Cerco chiavi primarie naturali e le uso dove posso.

Se non è possibile trovare chiavi naturali, preferisco un GUID a un INT ++ perché SQL Server usa gli alberi ed è male aggiungere sempre le chiavi alla fine negli alberi.

Sulle tabelle che sono accoppiamenti molti-a-molti uso una chiave primaria composta delle chiavi esterne.

Poiché sono abbastanza fortunato da utilizzare SQL Server, posso studiare piani di esecuzione e statistiche con il profiler e l'analizzatore di query e scoprire come le mie chiavi funzionano molto facilmente.


Hai della documentazione per eseguire il backup di questa affermazione: "se non è possibile trovare chiavi naturali, preferisco un GUID a un INT ++ perché SQL Server usa gli alberi ed è male aggiungere sempre le chiavi alla fine negli alberi". Non scettico, sto solo cercando di compilare della documentazione.
Lloyd Cotten,

1
@Lloyd - Sono contento che ti interessi a qualcosa che trovo molto affascinante. Un buon punto di partenza su msdn.microsoft.com/en-us/library/ms177443(SQL.90).aspx
Guge,

2

Uso sempre un numero automatico o un campo identità.

Ho lavorato per un client che aveva usato SSN come chiave primaria e quindi, a causa delle normative HIPAA, sono stato costretto a passare a un "MemberID" e questo ha causato molti problemi durante l'aggiornamento delle chiavi esterne nelle tabelle correlate. Attenersi a uno standard coerente di una colonna di identità mi ha aiutato a evitare un problema simile in tutti i miei progetti.


6
La scarsa selezione di una chiave naturale da parte di uno sviluppatore non significa che le chiavi naturali siano cattive.
Tom H,

1
Uno strumento difficile da usare non è in qualche modo un punto contro quello strumento?
Sqeaky

1

Tutte le tabelle dovrebbero avere una chiave primaria. Altrimenti, quello che hai è un HEAP - questo, in alcune situazioni, potrebbe essere quello che vuoi (carico di inserimento pesante quando i dati vengono quindi replicati tramite un broker di servizi in un altro database o tabella, ad esempio).

Per le tabelle di ricerca con un basso volume di righe, è possibile utilizzare un codice 3 CHAR come chiave primaria poiché occupa meno spazio di un INT, ma la differenza di prestazioni è trascurabile. A parte questo, userei sempre un INT a meno che tu non abbia una tabella di riferimento che forse ha una chiave primaria composita composta da chiavi esterne da tabelle associate.


1

Se vuoi davvero leggere tutto il avanti e indietro in questo antico dibattito, fai una ricerca della "chiave naturale" su Stack Overflow. Dovresti recuperare le pagine dei risultati.


1

I GUID possono essere usati come chiave primaria, ma è necessario creare il giusto tipo di GUID in modo che funzioni bene.

È necessario generare GUID COMB. Un buon articolo a riguardo e statistiche sulle prestazioni è Il costo dei GUID come chiavi primarie .

Inoltre, alcuni codici sulla creazione di GUID COMB in SQL sono in Uniqueidentifier vs identity ( archivio ) .


5
IMHO, guid's dovrebbe essere usato solo quando è necessario sincronizzare i dati tra database. In cui un ID generato automaticamente è problematico. La differenza tra l'uso di un guid e l'uso di un tipo numerico di base è che un guid richiederà 16 byte per riga, mentre un numero sarà molto più piccolo.
Logicalmind,

Se vai al link che ho fornito sopra, c'è poca differenza nelle prestazioni usando le guide COMB.
Donny V.,

0

Facciamo molti join e le chiavi primarie composite sono appena diventate un maiale alle prestazioni. Un int semplice o lungo si occupa di molti problemi anche se si sta introducendo una seconda chiave candidata, ma è molto più facile e comprensibile unirsi su un campo contro tre.


1
Questa strategia cade quando devi attraversare 6 tabelle per unire le due tabelle effettive necessarie perché le chiavi composite non sono state propagate. Si finisce anche per richiedere l'uso di loop / cursori per inserti multipli che possono essere un enorme ostacolo alle prestazioni.
Tom H,

2
Non sono troppo grande per imparare qualcosa di nuovo. Mi piacerebbe vedere un esempio di ciò che stai dicendo, sarebbe utile iniettare un piccolo fatto razionale in alcuni di questi argomenti religiosi.
Dan Blair l'

0

Sarò in anticipo sulle mie preferenze per le chiavi naturali - usale dove possibile, in quanto renderanno la tua vita di amministrazione del database molto più semplice. Ho stabilito uno standard nella nostra azienda in base al quale tutte le tabelle hanno le seguenti colonne:

  • ID riga (GUID)
  • Creatore (stringa; ha un valore predefinito del nome dell'utente corrente ( SUSER_SNAME()in T-SQL))
  • Creato (DateTime)
  • timestamp

L'ID riga ha una chiave univoca per tabella e, in ogni caso, viene generato automaticamente per riga (e le autorizzazioni impediscono a chiunque di modificarlo) ed è ragionevolmente garantito che sia univoco in tutte le tabelle e tutti i database. Se qualsiasi sistema ORM necessita di una chiave ID singola, questa è quella da utilizzare.

Nel frattempo, l'attuale PK è, se possibile, una chiave naturale. Le mie regole interne sono simili a:

  • Persone: utilizzare la chiave surrogata, ad esempio INT. Se è interno, il GUID dell'utente di Active Directory è una scelta accettabile
  • Tabelle di ricerca (ad esempio StatusCodes): utilizzare un codice CHAR breve; è più facile da ricordare degli INT, e in molti casi i moduli cartacei e gli utenti lo useranno anche per brevità (ad es. Status = "E" per "Scaduto", "A" per "Approvato", "NADIS" per "Nessun rilevamento di amianto Nel campione ")
  • Tabelle di collegamento - combinazione di FK (ad es. EventId, AttendeeId)

Quindi idealmente si finisce con un PK naturale, leggibile e memorabile dall'uomo, e un GUID ID-per-tavolo compatibile con ORM.

Avvertenza: i database che conservo tendono a 100.000 record anziché a milioni o miliardi, quindi se hai esperienza di sistemi più grandi che controindicano i miei consigli, sentiti libero di ignorarmi!


1
Stai suggerendo di creare entrambi GUID e INT SK per le tabelle senza una chiave naturale forte?

Non è necessario, ma i vantaggi sono: a) semplifica la replica se necessario, b) quando si ha a che fare con ORM, è possibile assegnare un ID univoco al proprio oggetto nel codice prima di salvarlo (che è utile se si devi fare molte modifiche sul tuo oggetto, magari salvandolo in una cache di sessione, prima di salvarlo). La chiave è l'INT in questa installazione; il GUID è solo un bonus.
Keith Williams,
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.