Domanda

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 di caratteri corti (x) o interi (o altri tipi numerici relativamente piccoli) che può fungere da colonna identificativa 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 a incremento automatico o una chiave primaria identificatore univoco.

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. Alcuni esempi:

  • datetime / carattere
  • datetime / intero
  • datetime / varchar
  • char / nvarchar / nvarchar

Esiste un caso valido per questo? Per questi casi avrei sempre definito un'identità o una colonna identificatore univoco.

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 c'erano 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 in questo metodo rispetto a una chiave surrogata / artificiale? Sto pensando principalmente alle prestazioni, alla manutenzione, all'amministrazione, ecc.?

È stato utile?

Soluzione

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 nella cache utilizzerai.
  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 " la 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 come questi "chiave primaria" può cambiare per le situazioni del mondo reale.

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, io uso 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.

Altri suggerimenti

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 sempre avere 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 salari dipendenti: (employee_id, start_date). Vorrei non creare un impiegato_salary_history_id artificiale. A che punto servirebbe (tranne " stolish consistency " )

Ovunque vengano utilizzate le chiavi artificiali, dovresti sempre dichiarare vincoli univoci sulle chiavi naturali. Ad esempio, usa state_id se è necessario, ma è meglio dichiarare un vincolo univoco su state_code, altrimenti alla fine finirai con:

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

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 altro).

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.CompanyId fa 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 CostElement e tabelle CostCentre , lo sarebbe.

Meno possibilità di sbagliare, meglio è.

Evito di usare le chiavi naturali per un semplice motivo: 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 scoperto 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.

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

Puoi utilizzare una colonna Identità (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: MODIFICA

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 in Nome, SocialNumber - 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 chiavi naturali e altri no.

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 questo potrebbe rallentare (dipende dal database) il processo. MA, dopo dovrebbe essere aggiunto.

Qualche commento sulla tabella dei collegamenti , è vero, è un'eccezione MA i campi dovrebbero essere FK per mantenere l'integrità, ed in alcuni casi quei campi possono essere anche chiavi primarie se duplicati nei collegamenti sono non autorizzato ... ma per mantenerlo in una forma semplice poiché l'eccezione è qualcosa di frequente nella programmazione, la chiave primaria dovrebbe essere presente per mantenere l'integrità dei tuoi dati.

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 ogni record.
  • Il valore di una 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 & # 8212; non puoi cambiare 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 l'articolo, vale la pena!)

Qual è la particolarità della 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è deve essere scelta per coerenza e utilizzo dei dati, non solo inserire prestazioni).

  • DA PARTE: purtroppo l'effetto collaterale della maggior parte dei database in fase di progettazione e sviluppato da programmatori di applicazioni (che a volte sono) che cosa è meglio per l'applicazione o il framework dell'applicazione spesso guida la scelta della chiave primaria per le tabelle. Questo porta a numeri interi e Chiavi GUID (in quanto semplici da usare per i framework delle applicazioni) e disegni monolitici di tavoli (poiché riducono il numero di applicazioni oggetti framework necessari per rappresentare i dati in memoria). Questi le decisioni di progettazione del database basate sull'applicazione portano a dati significativi problemi di coerenza se utilizzati su larga scala. Framework applicativi progettato in questo modo porta naturalmente alla progettazione di tavoli alla volta. & # 8220; Record parziali & # 8221; vengono creati in tabelle e dati inseriti nel tempo. L'interazione su più tavoli viene evitata o quando utilizzata provoca incoerenza dati quando l'applicazione funziona in modo errato. Questi disegni portano ai dati privi di significato (o di difficile comprensione), diffusione dei dati sui tavoli (devi dare un'occhiata ad altri tavoli per dare un senso al 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 essere sempre 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 & # 8216; Elaborato & # 8217; a & # 8216; Annullato & # 8217; corromperesti 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 pr

Una chiave naturale, se disponibile, è in genere la migliore. Quindi, se datetime / char in modo univoco identifica 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 di identificazione.

Le chiavi naturali contro quelle artificiali per me sono una questione di quanta logica aziendale desideri nel tuo database. 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.

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

A parte, GUIDs come chiave primaria può essere un maiale alle prestazioni. Non lo consiglierei.

Dovresti usare una chiave primaria "composita" o "composta" che comprende più campi.

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

Anch'io uso sempre una colonna ID numerica. In Oracle uso il numero (18,0) per nessuna ragione reale al di sopra del numero (12,0) (o qualunque sia un int anziché 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 unici su altre combinazioni di colonne, ma mi piace molto il mio ID, i requisiti di base creati e modificati.

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.

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

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

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

  • Tutte le tabelle dovrebbero avere una chiave primaria a colonna singola che auto incrementi.
  • Includilo in qualsiasi vista che si intende aggiornare
  • 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 altro che identificare una determinata entità o relativa a una determinata entità.

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

Utilizza indici aggiuntivi per supportare chiavi multi-colonna che hanno un significato nella tua applicazione.

Uso sempre un numero automatico o un campo identità.

Ho lavorato per un cliente che aveva usato SSN come chiave primaria e quindi a causa delle normative HIPAA sono stato costretto a passare a un "MemberID" e 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.

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.

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

GUIDs può essere utilizzato come chiave primaria, ma è necessario creare il tipo giusto di GUID in modo che funzioni bene.

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

Anche un po 'di codice sulla costruzione di GUID COMB in SQL è in Uniqueidentifier vs identity ( archivio ) .

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 anziché tre.

Sarò in anticipo sulle mie preferenze per le chiavi naturali: usale dove possibile, poiché 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: utilizza la chiave surrogata, ad es. INT. Se è interno, il GUID dell'utente di Active Directory è una scelta accettabile
  • Tabelle di ricerca (ad es. 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 " Approved " ;, " NADIS " per " Nessun amianto rilevato 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 a ID 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 il mio consiglio, sentiti libero di ignorarmi!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top