it-swarm.it

Surrogato vs. chiavi naturali / aziendali

Eccoci di nuovo, la vecchia discussione sorge ancora ...

Dovremmo avere una chiave di business come chiave primaria o preferiremmo avere un ID surrogato (ovvero un'identità di SQL Server) con un vincolo univoco sul campo della chiave di business?

Fornisci esempi o prove a supporto della tua teoria.

163
Manrico Corazzi

Tutti e due. Prendi la tua torta e mangiala.

Ricorda che non c'è nulla di speciale in una chiave primaria, tranne che è etichettata come tale. Non è altro che un vincolo NOT NULL UNIQUE e una tabella può avere più di uno.

Se si utilizza una chiave surrogata, si desidera comunque una chiave aziendale per garantire l'univocità in base alle regole aziendali.

91
Ted

Solo alcuni motivi per usare le chiavi surrogate:

  1. Stabilità: la modifica di una chiave a causa di un'attività o di un'esigenza naturale influirà negativamente sulle tabelle correlate. Le chiavi surrogate raramente, se mai, devono essere modificate perché non vi è alcun significato legato al valore.

  2. Convenzione: ti consente di avere una convenzione standardizzata di denominazione delle colonne della chiave primaria piuttosto che dover pensare a come unire le tabelle con vari nomi per i loro PK.

  3. Velocità: A seconda del valore e del tipo PK, una chiave surrogata di un numero intero può essere più piccola, più veloce da indicizzare e cercare.

113
Jay Shepherd

Sembra che nessuno abbia ancora detto nulla a sostegno di chiavi non surrogate (esito a dire "naturale"). Quindi ecco qui ...

Uno svantaggio delle chiavi surrogate è che sono prive di significato (citate come vantaggio da alcuni, ma ...). Questo a volte ti costringe a unire molte più tabelle alla tua query di quanto dovrebbe essere realmente necessario. Confrontare:

select sum(t.hours)
from timesheets t
where t.dept_code = 'HR'
and t.status = 'VALID'
and t.project_code = 'MYPROJECT'
and t.task = 'BUILD';

contro:

select sum(t.hours)
from timesheets t
     join departents d on d.dept_id = t.dept_id
     join timesheet_statuses s on s.status_id = t.status_id
     join projects p on p.project_id = t.project_id
     join tasks k on k.task_id = t.task_id
where d.dept_code = 'HR'
and s.status = 'VALID'
and p.project_code = 'MYPROJECT'
and k.task_code = 'BUILD';

A meno che qualcuno non pensi seriamente che sia una buona idea:

select sum(t.hours)
from timesheets t
where t.dept_id = 34394
and t.status_id = 89    
and t.project_id = 1253
and t.task_id = 77;

"Ma" qualcuno dirà "cosa succede quando il codice per MYPROJECT o VALID o HR cambia?" Alla quale la mia risposta sarebbe: "perché dovresti bisogno di cambiarlo?" Queste non sono chiavi "naturali", nel senso che qualche ente esterno legifererà che d'ora in poi "VALID" dovrebbe essere ricodificato come "BUONO". Solo una piccola percentuale di chiavi "naturali" rientra davvero in quella categoria - SSN e codice postale sono i soliti esempi. Utilizzerei sicuramente un tasto numerico insignificante per tabelle come Persona, Indirizzo - ma non per tutto , che per qualche motivo la maggior parte delle persone qui sembrano sostenere.

Vedi anche: la mia risposta a un'altra domanda

67
Tony Andrews

La chiave surrogata non avrà MAI un motivo per cambiare. Non posso dire lo stesso delle chiavi naturali. Cognome, e-mail, nubmers ISBN: tutti possono cambiare un giorno.

29
Rimantas

Le chiavi surrogate (in genere numeri interi) hanno il valore aggiunto di rendere più veloci le relazioni tra tabelle e una maggiore velocità di archiviazione e velocità di aggiornamento (ancora meglio, le chiavi esterne non devono essere aggiornate quando si utilizzano chiavi surrogate, a differenza dei campi chiave aziendale, che cambiano di tanto in tanto).

La chiave primaria di una tabella deve essere utilizzata per identificare in modo univoco la riga, principalmente per scopi di join. Pensa a una tabella Persone: i nomi possono cambiare e non sono garantiti univoci.

Pensa alle aziende: sei una felice azienda Merkin che fa affari con altre società in Merkia. Sei abbastanza intelligente da non usare il nome dell'azienda come chiave primaria, quindi usi l'ID azienda univoco del governo Merkia in tutti i suoi 10 caratteri alfanumerici. Quindi Merkia cambia gli ID dell'azienda perché hanno pensato che sarebbe stata una buona idea. Va bene, usi la funzionalità di aggiornamento in cascata del tuo motore db, per una modifica che non dovrebbe coinvolgerti in primo luogo. Successivamente, la tua attività si espande e ora lavori con un'azienda in Freedonia. L'ID società freedonian ha un massimo di 16 caratteri. È necessario ingrandire la chiave primaria dell'ID azienda (anche i campi della chiave esterna in Ordini, Problemi, Trasferimenti di denaro ecc.), Aggiungendo un campo Paese nella chiave primaria (anche nelle chiavi esterne). Ahia! Guerra civile in Freedonia, è divisa in tre paesi. Il nome del paese del tuo associato dovrebbe essere cambiato in quello nuovo; aggiornamenti in cascata per il salvataggio. A proposito, qual è la tua chiave primaria? (Paese, ID azienda) o (ID azienda, Paese)? Il secondo aiuta ad aderire, il primo evita un altro indice (o forse molti, se vuoi che anche i tuoi ordini vengano raggruppati per paese).

Tutti questi non sono una prova, ma un'indicazione che una chiave surrogata per identificare in modo univoco una riga per tutti gli usi, comprese le operazioni di join, è preferibile a una chiave aziendale.

29
tzot

Odio le chiavi surrogate in generale. Dovrebbero essere utilizzati solo quando non è disponibile una chiave naturale di qualità. È piuttosto assurdo quando ci pensi, pensare che l'aggiunta di dati insignificanti alla tua tabella possa migliorare le cose.

Ecco i miei motivi:

  1. Quando si usano le chiavi naturali, le tabelle sono raggruppate nel modo in cui vengono spesso cercate, rendendo le query più veloci.

  2. Quando si utilizzano chiavi surrogate è necessario aggiungere indici univoci su colonne di chiavi logiche. È ancora necessario impedire dati duplicati logici. Ad esempio, non puoi consentire a due organizzazioni con lo stesso nome nella tabella Organizzazione anche se pk è una colonna ID surrogata.

  3. Quando le chiavi surrogate vengono utilizzate come chiave primaria, è molto meno chiaro quali siano le chiavi primarie naturali. Durante lo sviluppo, vuoi sapere quale set di colonne rende unica la tabella.

  4. In una o più catene di relazioni, le catene chiave logiche. Ad esempio, le organizzazioni hanno molti account e gli account hanno molte fatture. Quindi la chiave logica dell'organizzazione è OrgName. La chiave logica di Account è OrgName, AccountID. La chiave logica di Invoice è OrgName, AccountID, InvoiceNumber.

    Quando vengono utilizzate chiavi surrogate, le catene chiave vengono troncate avendo solo una chiave esterna per il genitore immediato. Ad esempio, la tabella delle fatture non ha una colonna OrgName. Ha solo una colonna per AccountID. Se desideri cercare fatture per una determinata organizzazione, dovrai unirti alle tabelle Organizzazione, Account e Fattura. Se si utilizzano chiavi logiche, è possibile eseguire una query direttamente nella tabella Organizzazione.

  5. La memorizzazione dei valori chiave surrogati delle tabelle di ricerca provoca il riempimento di tabelle con numeri interi senza significato. Per visualizzare i dati, è necessario creare viste complesse che si uniscano a tutte le tabelle di ricerca. Una tabella di ricerca deve contenere un set di valori accettabili per una colonna. Non dovrebbe essere codificato memorizzando invece una chiave surrogata intera. Non c'è nulla nelle regole di normalizzazione che suggerisce che è necessario memorizzare un numero intero surrogato invece del valore stesso.

  6. Ho tre diversi libri di database. Nessuno di loro mostra l'uso di chiavi surrogate.

26
Ken

Voglio condividere la mia esperienza con te in questa guerra infinita: D sul dilemma chiave naturale vs surrogato. Penso che sia le chiavi surrogate (quelle generate automaticamente artificiali) sia le chiavi naturali (composte da colonne con significato di dominio) hanno pro e contro . Quindi, a seconda della situazione, potrebbe essere più pertinente scegliere un metodo o l'altro.

Poiché sembra che molte persone presentino chiavi surrogate come la soluzione quasi perfetta e chiavi naturali come la peste, mi concentrerò sugli argomenti dell'altro punto di vista:

Svantaggi delle chiavi surrogate

Le chiavi surrogate sono:

  1. Fonte dei problemi di prestazione:
    • Di solito sono implementati usando colonne auto-incrementate che significano:
      • Un viaggio di andata e ritorno nel database ogni volta che si desidera ottenere un nuovo ID (so che questo può essere migliorato usando la cache o algoritmi simili [seq] hilo ma comunque questi metodi hanno i loro svantaggi).
      • Se un giorno dovessi spostare i tuoi dati da uno schema all'altro (succede almeno abbastanza regolarmente nella mia azienda), potresti riscontrare problemi di collisione dell'ID. E sì, lo so che puoi usare gli UUID, ma questi ultimi richiedono 32 cifre esadecimali! (Se ti interessa la dimensione del database, può trattarsi di un problema).
      • Se stai usando una sequenza per tutte le tue chiavi surrogate, allora - sicuramente - finirai con una contesa sul tuo database.
  2. Soggetto a errori. Una sequenza ha un limite max_value quindi - come sviluppatore - devi porre attenzione ai seguenti punti:
    • È necessario scorrere la sequenza (quando viene raggiunto il valore massimo, torna a 1,2, ...).
    • Se si utilizza la sequenza come un ordine (nel tempo) dei dati, è necessario gestire il caso del ciclo (la colonna con ID 1 potrebbe essere più recente della riga con valore massimo ID - 1).
    • Assicurati che il tuo codice (e anche le tue interfacce client che non dovrebbero accadere come dovrebbe essere un ID interno) supporta numeri interi 32b/64b che hai usato per memorizzare i valori della sequenza.
  3. Non garantiscono dati non duplicati. Puoi sempre avere 2 righe con tutti gli stessi valori di colonna ma con un valore generato diverso. Per me questo è [~ # ~] il problema [~ # ~] delle chiavi surrogate dal punto di vista della progettazione del database.
  4. Altro su Wikipedia ...

Miti su chiavi naturali

  1. Le chiavi composite sono meno inefficienti delle chiavi surrogate. No! Dipende dal motore di database utilizzato:
  2. Le chiavi naturali non esistono nella vita reale. Scusa ma esistono! Nell'industria aeronautica, ad esempio, la seguente Tupla sarà sempre unica per quanto riguarda un determinato volo programmato (compagnia aerea, giorno di partenza, numero di volo, operativoSuffix). Più in generale, quando un set di dati aziendali è garantito come unico da un determinato standard , questo set di dati è un candidato chiave [buono] naturale.
  3. Le chiavi naturali "inquinano lo schema" delle tabelle figlio. Per me questo è più un sentimento che un vero problema. Avere una chiave primaria a 4 colonne di 2 byte ciascuna potrebbe essere più efficiente di una singola colonna di 11 byte. Inoltre, le 4 colonne possono essere utilizzate per interrogare direttamente la tabella figlio (usando le 4 colonne in una clausola where) senza unirsi alla tabella padre.

Conclusione

Usa le chiavi naturali quando è importante farlo e usa le chiavi surrogate quando è meglio usarle.

Spero che questo abbia aiutato qualcuno!

17
mwnsiri

Usa sempre una chiave che non ha significato commerciale. È solo una buona pratica.

EDIT: stavo cercando di trovare un link online, ma non ci sono riuscito. Comunque in 'Patterns of Enterprise Archtecture' [Fowler] ha una buona spiegazione del perché non dovresti usare nient'altro che una chiave senza altro significato che essere una chiave. Si riduce al fatto che dovrebbe avere un lavoro e un solo lavoro.

15
Iain Holder

Le chiavi surrogate sono molto utili se si prevede di utilizzare uno strumento ORM per gestire/generare le classi di dati. Mentre puoi usare chiavi composite con alcuni dei mappatori più avanzati (leggi: ibernazione), aggiunge una certa complessità al tuo codice.

(Naturalmente, i puristi del database sostengono che anche la nozione di chiave surrogata è un abominio.)

Sono un fan dell'uso degli uid per le chiavi surrogate quando è adatto. La principale vittoria con loro è che conosci la chiave in anticipo, ad es. puoi creare un'istanza di una classe con l'ID già impostato e garantito come univoco, mentre con, per esempio, una chiave intera dovrai settare 0 o -1 e aggiornare ad un valore appropriato quando salvi/aggiorni.

Gli UID hanno delle penalità in termini di ricerca e velocità di join, quindi dipende dall'applicazione in questione se sono desiderabili.

9
Derek Lawless

L'utilizzo di una chiave surrogata è meglio secondo me in quanto non vi è alcuna possibilità che cambi. Quasi tutto ciò a cui riesco a pensare che potresti usare come chiave naturale potrebbe cambiare (disclaimer: non sempre vero, ma comunemente).

Un esempio potrebbe essere un DB di auto: a prima vista, potresti pensare che la targa possa essere utilizzata come chiave. Ma questi potrebbero essere cambiati in modo che sarebbe una cattiva idea. Non vorrai davvero scoprirlo after rilasciando l'app, quando qualcuno viene da te che vuole sapere perché non può cambiare la sua targa con la sua nuova brillante personalizzata.

6
Mark Embling

Utilizzare sempre una sola colonna, chiave surrogata, se possibile. Ciò rende i join, nonché gli inserti/gli aggiornamenti/le eliminazioni molto più puliti perché sei responsabile solo di tenere traccia di una singola informazione per mantenere il record.

Quindi, se necessario, impila le chiavi della tua azienda come contorni o indici univoci. Ciò manterrà intatta l'integrità dei dati.

La logica aziendale/le chiavi naturali possono cambiare, ma la chiave fisica di una tabella non dovrebbe MAI cambiare.

5
user7658

In uno scenario di datawarehouse credo sia meglio seguire il percorso chiave surrogato. Due motivi:

  • Sei indipendente dal sistema di origine e le modifiche lì, ad esempio una modifica del tipo di dati, non influiranno su di te.
  • Il tuo DW avrà bisogno di meno spazio fisico poiché utilizzerai solo tipi di dati interi per le tue chiavi surrogate. Anche i tuoi indici funzioneranno meglio.
4
Santiago Cepas

Questo è uno di quei casi in cui una chiave surrogata è praticamente sempre ha senso. Ci sono casi in cui puoi scegliere ciò che è meglio per il database o ciò che è meglio per il tuo modello di oggetto, ma in entrambi i casi, usare una chiave insignificante o GUID è un'idea migliore. Rende l'indicizzazione più semplice e più veloce ed è un'identità per il tuo oggetto che non cambia.

2
Charles Graham

Ricordiamo che non è buona norma posizionare indici cluster su chiavi surrogate casuali, ad esempio GUID che leggono XY8D7-DFD8S, poiché SQL Server non è in grado di ordinare fisicamente questi dati. Dovresti invece posizionare indici univoci su questi dati, anche se può essere utile eseguire semplicemente il profiler SQL per le operazioni della tabella principale e quindi posizionare tali dati in Ottimizzazione guidata motore di database.

Vedi thread @ http://social.msdn.Microsoft.com/Forums/en-us/sqlgetstarted/thread/27bd9c77-ec31-44f1-ab7f-bd2cb13129be

2
Bryan Swan

Caso 1: La tabella è una tabella di ricerca con meno di 50 tipi (inserti)

Usa chiavi aziendali/naturali. Per esempio:

Table: JOB with 50 inserts
CODE (primary key)       NAME               DESCRIPTION
PRG                      PROGRAMMER         A programmer is writing code
MNG                      MANAGER            A manager is doing whatever
CLN                      CLEANER            A cleaner cleans
...............
joined with
Table: PEOPLE with 100000 inserts

foreign key JOBCODE in table PEOPLE
looks at
primary key CODE in table JOB

Caso 2: La tua tabella è una tabella con migliaia di inserti

Usa chiavi surrogate/autoincremento. Per esempio:

Table: ASSIGNMENT with 1000000 inserts
joined with
Table: PEOPLE with 100000 inserts

foreign key PEOPLEID in table ASSIGNMENT
looks at
primary key ID in table PEOPLE (autoincrement)

Nel primo caso:

  • È possibile selezionare tutti i programmatori nella tabella PEOPLE senza utilizzare join con la tabella JOB, ma solo con: "SELEZIONA * DA PERSONE DOVE JOBCODE = 'PRG'"

Nel secondo caso:

  • Le query del database sono più veloci perché la chiave primaria è un numero intero
  • Non è necessario preoccuparsi di trovare la chiave univoca successiva poiché il database stesso fornisce il prossimo incremento automatico.
2
Stefanos Kargas

Le chiavi surrogate possono essere utili quando le informazioni aziendali possono cambiare o essere identiche. I nomi delle imprese non devono essere univoci in tutto il paese, dopo tutto. Supponiamo che tu abbia a che fare con due aziende di nome Smith Electronics, una nel Kansas e una nel Michigan. Puoi distinguerli per indirizzo, ma questo cambierà. Anche lo stato può cambiare; cosa succederebbe se Smith Electronics di Kansas City, Kansas si spostasse attraverso il fiume a Kansas City, Missouri? Non esiste un modo ovvio di mantenere distinte queste attività con informazioni chiave naturali, quindi una chiave surrogata è molto utile.

Pensa alla chiave surrogata come a un numero ISBN. Di solito, identifichi un libro per titolo e autore. Tuttavia, ho due libri intitolati "Pearl Harbor" di H. P. Willmott, e sono sicuramente libri diversi, non solo edizioni diverse. In un caso del genere, potrei fare riferimento all'aspetto dei libri, o il precedente rispetto al successivo, ma è altrettanto bene che ho il codice ISBN su cui ripiegare.

2
David Thornley

Cavallo per corsi. Per dichiarare il mio pregiudizio; Prima sono uno sviluppatore, quindi mi occupo principalmente di fornire agli utenti un'applicazione funzionante.

Ho lavorato su sistemi con chiavi naturali e ho dovuto dedicare molto tempo ad assicurarmi che le variazioni di valore si propagassero.

Ho lavorato su sistemi con solo chiavi surrogate e l'unico inconveniente è stata la mancanza di dati denormalizzati per il partizionamento.

La maggior parte degli sviluppatori PL/SQL tradizionali con cui ho lavorato non amava le chiavi surrogate a causa del numero di tabelle per join, ma i nostri database di test e produzione non hanno mai sudato; i join extra non hanno influito sulle prestazioni dell'applicazione. Con dialetti di database che non supportano clausole come "X inner join Y on Xa = Yb" o sviluppatori che non usano quella sintassi, i join extra per le chiavi surrogate rendono le query più difficili da leggere e più lunghe da digitare e controlla: vedi il post di @Tony Andrews. Ma se usi un ORM o qualsiasi altro framework di generazione SQL non lo noterai. Anche la digitazione tattile si attenua.

1
WillC

Forse non è completamente pertinente a questo argomento, ma ho mal di testa con le chiavi surrogate. L'analisi Oracle pre-consegnata crea SK generati automaticamente su tutte le sue tabelle dimensionali nel magazzino e memorizza anche quelli sui fatti. Pertanto, ogni volta che devono essere ricaricate (dimensioni) quando vengono aggiunte nuove colonne o devono essere popolate per tutti gli elementi nella dimensione, gli SK assegnati durante l'aggiornamento rendono gli SK non sincronizzati con i valori originali memorizzati nel fatto, forzando una ricarica completa di tutte le tabelle dei fatti che vi si uniscono. Preferirei che anche se la SK fosse un numero insignificante, ci sarebbe un modo in cui non potrebbe cambiare per i record originali/vecchi. Come molti sanno, il pronto intervento raramente soddisfa le esigenze di un'organizzazione e dobbiamo personalizzare costantemente. Ora disponiamo di dati per un valore di 3 anni nel nostro magazzino e le ricariche complete dai sistemi finanziari Oracle sono molto grandi. Quindi, nel mio caso, non vengono generati dall'immissione dei dati, ma aggiunti in un magazzino per aiutare a riportare le prestazioni. Ho capito, ma i nostri cambiano ed è un incubo.

1
lrb

Nel caso del database point in time è meglio avere una combinazione di chiavi surrogate e chiavi naturali. per esempio. devi tenere traccia delle informazioni di un socio per un club. Alcuni attributi di un membro non cambiano mai. ad es. Data di nascita ma il nome può cambiare. Quindi crea una tabella Member con una chiave surrogata member_id e disponi di una colonna per DOB. Crea un'altra tabella chiamata nome persona e disponi di colonne per member_id, member_fname, member_lname, date_updated. In questa tabella la chiave naturale sarebbe member_id + date_updated.

0
kanad