Le chiavi esterne sono davvero necessarie nella progettazione di un database?


109

Per quanto ne so, le chiavi esterne (FK) vengono utilizzate per aiutare il programmatore a manipolare i dati nel modo corretto. Supponiamo che un programmatore lo stia già facendo nel modo giusto, allora abbiamo davvero bisogno del concetto di chiavi esterne?

Esistono altri usi per le chiavi esterne? Mi manca qualcosa qui?


2
Questo succede spesso da queste parti. Do la colpa a Joel Spolsky :-). Ci sono molte buone risposte qui; piuttosto che retype mia, mi limiterò a dare un link: stackoverflow.com/questions/83147/whats-wrong-with-foreign-keys
SquareCog

70
"Supponiamo che un programmatore lo stia già facendo nel modo giusto" - Non riesco nemmeno a immaginare uno scenario del genere.
ricorsivo

11
"Foreign Key" è un'idea, non una tecnologia. È una regola relazionale. La tua domanda è davvero se dovresti tentare di applicare la regola nel tuo codice o lasciare che il database ti aiuti. Quando è coinvolta la concorrenza, è meglio lasciare che il motore di database imponga la regola, poiché è a conoscenza di TUTTO ciò che accade nel database, mentre il tuo codice non può essere a conoscenza.
Triynko

5
@lubos & cdeszaq. In realtà, è una regola relazionale ... è un sottoinsieme della regola 10 dei "Twleve Commandments" di Codd ... "Integrity Independence", che sostanzialmente dice che l'integrità relazionale dell'RDBMS deve essere mantenuta indipendentemente da qualsiasi applicazione che vi acceda, che è esattamente quello che stavo spiegando in modo facile da capire. Questa regola viene implementata, tra le altre cose, da vincoli di chiave esterna. Quindi sì, l'idea di una chiave esterna è "una" regola relazionale.
Triynko

1
@lubos: Per chiarire, stai parlando se utilizzerai o meno una particolare funzionalità, ma sto parlando se la presenza di quella funzionalità è necessaria per avere un RDBMS completo e pienamente funzionante. I vincoli referenziali, se e quando si sceglie di usarli, è qualcosa che dovrebbe essere applicato all'interno dell'RDBMS (piuttosto che nell'applicazione), quindi è una caratteristica che dovrebbe esserci, e in questo senso è un requisito del modello relazionale se svilupperai un RDBMS completo.
Triynko

Risposte:


102

Le chiavi esterne aiutano a rafforzare l'integrità referenziale a livello di dati. Migliorano anche le prestazioni perché normalmente sono indicizzati per impostazione predefinita.


52
Se hai bisogno di un indice creane uno, questo non dovrebbe essere il motivo principale per FK. (Infatti in alcune circostanze (ad esempio, più inserimenti di quelli selezionati) mantenere un FK potrebbe essere più lento.)
Robert

7
Questa è una risposta orribile. Gli FK in genere possono aggiungere un sovraccarico extra non migliorare le prestazioni.
Agile Jedi

In SQL-Server, non sono indicizzati per impostazione predefinita né sull'arbitro né sul referrer. sqlskills.com/blogs/kimberly/…
user420667

1
Né in Oracle; devi creare tu stesso gli indici (sulle colonne FK).
Littlefoot

58

Le chiavi esterne possono anche aiutare il programmatore a scrivere meno codice usando cose come ON DELETE CASCADE. Ciò significa che se hai una tabella contenente utenti e un'altra contenente ordini o qualcosa del genere, l'eliminazione di un utente potrebbe eliminare automaticamente tutti gli ordini che puntano a quell'utente.


3
@ Greg Hewgill Questo potrebbe potenzialmente portare a molti problemi. Dovresti stare molto attento con pensieri come DELETE CASCADE, poiché in molti casi, vorresti mantenere gli ordini creati da un utente quando lo elimini.
Kibbee

8
Sebbene questo dovrebbe probabilmente essere gestito a livello di logica aziendale. Decidere se conservare o meno i record secondari correlati non è esattamente la stessa cosa che assicurarsi che nessun valore violi le relazioni di chiave esterna.
Codewerks

5
L'altro problema è il controllo, se il controllo non viene eseguito a livello di database, aggiornamenti o eliminazioni a cascata invalideranno il percorso di controllo.
si618

@Codewerks: la logica aziendale può essere nel DB.
Fantius

44

Non riesco a immaginare di progettare un database senza chiavi esterne. Senza di loro, alla fine sei destinato a commettere un errore e corrompere l'integrità dei tuoi dati.

Non sono necessari , in senso stretto, ma i vantaggi sono enormi.

Sono abbastanza certo che FogBugz non abbia vincoli di chiave esterna nel database. Sarei interessato a sapere come il team di Fog Creek Software struttura il proprio codice per garantire che non introdurrà mai un'incongruenza.


43
Joel: "Finora non abbiamo mai avuto problemi". Finora non sono mai entrato in un lampione. Ma continuo a pensare che sia una buona idea indossare le cinture di sicurezza ;-)
Tony Andrews

2
Forse non hai mai visto il problema, ma potrebbe essere che c'è ... La maggior parte dei database usa una convenzione come id_xxx che è esattamente la stessa di ixXXX
FerranB

1
@ Joel: convenzioni di denominazione al posto dell'applicazione delle regole? Tanto vale eliminare il tipo mentre ci sei.
jcollum

8
@Eric: Stai sostenendo Fog Creek come una sorta di avatar dello sviluppo del software qui. Se dicessi "Una società a New York City non ha chiavi esterne nel proprio db ..." diremmo tutti "E?"
jcollum

3
Eric: FogBugz utilizza una convenzione di denominazione per le chiavi esterne. Ad esempio ixBug è inteso come un indice nella chiave primaria della tabella Bug. Finora non abbiamo mai avuto problemi. - Joel Spolsky
Sam Saffron

40

Uno schema di database senza vincoli FK è come guidare senza cintura di sicurezza.

Un giorno te ne pentirai. Non spendere quel poco di tempo in più sui fondamenti del design e sull'integrità dei dati è un modo sicuro per garantire mal di testa in seguito.

Accettereste codice nella vostra applicazione che era così sciatto? Ciò accedeva direttamente agli oggetti membri e modificava direttamente le strutture dati.

Perché pensi che ciò sia stato reso difficile e persino inaccettabile nelle lingue moderne?


2
+1 per una buona analogia tra incapsulamento e relazioni FK / PK.
jcollum

21

Sì.

  1. Ti mantengono onesto
  2. Mantengono onesti i nuovi sviluppatori
  3. Tu puoi fare ON DELETE CASCADE
  4. Ti aiutano a generare bei diagrammi che spiegano da soli i collegamenti tra le tabelle

1
cosa intendi per onestà?
dspacejs

Onesto con la concezione immagino. Ti impedisce di barare con i dati eseguendo una programmazione rapida e zoppa.
Oreste Viron

13

Supponiamo che un programmatore lo stia già facendo nel modo giusto

Fare una tale supposizione mi sembra un'idea estremamente cattiva; in generale il software è fenomenalmente buggato.

E questo è il punto, davvero. Gli sviluppatori non riescono a fare le cose per bene, quindi assicurarsi che il database non possa essere riempito con dati non validi è una buona cosa.

Sebbene in un mondo ideale, i join naturali utilizzerebbero le relazioni (cioè i vincoli FK) piuttosto che i nomi delle colonne corrispondenti. Ciò renderebbe gli FK ancora più utili.


2
Buon punto, sarebbe bello unire due tabelle con "ON [Relationship]" o qualche altra parola chiave e lasciare che il db capisca quali colonne sono coinvolte. Sembra davvero ragionevole.
jcollum

13

Personalmente sono a favore delle chiavi esterne perché formalizza la relazione tra le tabelle. Mi rendo conto che la tua domanda presuppone che il programmatore non stia introducendo dati che violerebbero l'integrità referenziale, ma ho visto troppi casi in cui l'integrità referenziale dei dati viene violata, nonostante le migliori intenzioni!

Vincoli di chiave pre-esterna (ovvero integrità referenziale dichiarativa o DRI) è stato speso molto tempo per implementare queste relazioni utilizzando i trigger. Il fatto che possiamo formalizzare la relazione con un vincolo dichiarativo è molto potente.

@ John - Altri database possono creare automaticamente indici per chiavi esterne, ma SQL Server no. In SQL Server, le relazioni di chiave esterna sono solo vincoli. È necessario definire il proprio indice sulle chiavi esterne separatamente (il che può essere di beneficio).

Modifica: vorrei aggiungere che, IMO, l'uso di chiavi esterne a supporto di ON DELETE o ON UPDATE CASCADE non è necessariamente una buona cosa. In pratica, ho scoperto che la cascata all'eliminazione dovrebbe essere attentamente considerata in base alla relazione dei dati - ad esempio, hai un genitore-figlio naturale in cui questo può essere OK o la tabella correlata è un insieme di valori di ricerca. L'utilizzo di aggiornamenti in cascata implica che si consenta la modifica della chiave primaria di una tabella. In tal caso, ho un disaccordo filosofico generale in quanto la chiave primaria di una tabella non dovrebbe cambiare. Le chiavi dovrebbero essere intrinsecamente costanti.


9

Senza una chiave esterna come si fa a dire che due record in tabelle diverse sono correlati?

Penso che ciò a cui ti riferisci sia l'integrità referenziale, in cui il record figlio non può essere creato senza un record genitore esistente ecc. Questi sono spesso noti come vincoli di chiave esterna, ma non devono essere confusi con l'esistenza di chiavi esterne in il primo posto.


8

C'è un vantaggio nel non avere chiavi esterne? A meno che tu non stia utilizzando un database scadente, gli FK non sono così difficili da configurare. Allora perché dovresti avere una politica per evitarli? Una cosa è avere una convenzione di denominazione che dica che una colonna fa riferimento a un'altra, un'altra è sapere che il database sta effettivamente verificando quella relazione per te.


8

Suppongo che tu stia parlando di vincoli di chiave esterna applicati dal database . Probabilmente stai già usando chiavi esterne, semplicemente non l'hai detto al database.

Supponiamo che un programmatore lo stia già facendo nel modo giusto, allora abbiamo davvero bisogno del concetto di chiavi esterne?

Teoricamente no. Tuttavia, non c'è mai stato un software senza bug.

I bug nel codice dell'applicazione in genere non sono così pericolosi: identifichi il bug e lo risolvi, dopodiché l'applicazione funziona di nuovo senza problemi. Ma se un bug consente ai dati in corso di esecuzione di entrare nel database, allora sei bloccato! È molto difficile ripristinare i dati danneggiati nel database.

Considera se un bug sottile in FogBugz ha consentito la scrittura di una chiave esterna corrotta nel database. Potrebbe essere facile correggere il bug e inviare rapidamente la correzione ai clienti in una versione di correzione di bug. Tuttavia, come dovrebbero essere corretti i dati corrotti in dozzine di database? Corretta codice potrebbe ora interrompersi improvvisamente perché i presupposti sull'integrità delle chiavi esterne non sono più validi.

Nelle applicazioni web in genere hai un solo programma che parla al database, quindi c'è solo un posto in cui i bug possono danneggiare i dati. In un'applicazione aziendale potrebbero esserci diverse applicazioni indipendenti che parlano allo stesso database (per non parlare delle persone che lavorano direttamente con la shell del database). Non c'è modo di essere sicuri che tutte le applicazioni seguano gli stessi presupposti senza bug, sempre e per sempre.

Se i vincoli sono codificati nel database, la cosa peggiore che può accadere con i bug è che all'utente viene mostrato un brutto messaggio di errore su alcuni vincoli SQL non soddisfatti. Questo è molto preferibile al lasciare che i dati correnti entrino nel database aziendale, dove a sua volta interromperà tutte le tue applicazioni o porterà semplicemente a tutti i tipi di output errati o fuorvianti.

Oh, e anche i vincoli di chiave esterna migliorano le prestazioni perché sono indicizzati per impostazione predefinita. Non riesco a pensare a nessun motivo per non utilizzare vincoli di chiave esterna.


7

Gli FK sono molto importanti e dovrebbero sempre esistere nel tuo schema, a meno che tu non sia eBay .


2
quel collegamento è in realtà estremamente affascinante ... mi piacerebbe davvero conoscere maggiori dettagli e ho un po 'paura di usare ebay ora. per altre persone: clicca sulla quarta domanda per vedere cosa dice sulla loro struttura db. Però vale la pena guardare l'intera intervista. anche ...unibrow
cupo.pinguino

6

Penso una cosa sola a un certo punto debba essere responsabile di assicurare relazioni valide.

Ad esempio, Ruby on Rails non utilizza chiavi esterne, ma convalida da solo tutte le relazioni. Se accedi al tuo database solo da quell'applicazione Ruby on Rails, va bene.

Tuttavia, se si dispone di altri client che scrivono nel database, senza chiavi esterne devono implementare la propria convalida. Hai quindi due copie del codice di convalida che sono molto probabilmente diverse, che qualsiasi programmatore dovrebbe essere in grado di dire è un peccato cardinale.

A quel punto, le chiavi esterne sono davvero necessarie, poiché consentono di spostare nuovamente la responsabilità su un unico punto.


2
È come una cipolla. Gli FK sono l'ultimo strato di difesa. A meno che non si tratti di un database locale incorporato, le app che cercano di eseguire l'integrità referenziale è sempre una cattiva idea.
Fabricio Araujo

5

Le chiavi esterne consentono a qualcuno che non ha mai visto il tuo database di determinare la relazione tra le tabelle.

Ora può andare tutto bene, ma pensa a cosa succederà quando il tuo programmatore se ne andrà e qualcun altro dovrà subentrare.

Le chiavi esterne consentiranno loro di comprendere la struttura del database senza passare attraverso migliaia di righe di codice.


5

Per quanto ne so, le chiavi esterne vengono utilizzate per aiutare il programmatore a manipolare i dati nel modo corretto.

Gli FK consentono all'amministratore di database di proteggere l'integrità dei dati dagli smarrimenti degli utenti quando il programmatore non riesce a farlo, e talvolta di proteggersi dagli smarrimenti dei programmatori.

Supponiamo che un programmatore lo stia già facendo nel modo giusto, allora abbiamo davvero bisogno del concetto di chiavi esterne?

I programmatori sono mortali e fallibili. Gli FK sono dichiarativi, il che li rende più difficili da sbagliare .

Esistono altri usi per le chiavi esterne? Mi manca qualcosa qui?

Sebbene non sia questo il motivo per cui sono stati creati, gli FK forniscono suggerimenti affidabili e forti agli strumenti di creazione di diagrammi e ai costruttori di query. Questo viene trasmesso agli utenti finali, che hanno un disperato bisogno di suggerimenti forti e affidabili.


Questa è un'ottima risposta.
Dan Lugg

4

Non sono strettamente necessarie, così come le cinture di sicurezza non sono strettamente necessarie. Ma possono davvero salvarti dal fare qualcosa di stupido che rovina il tuo database.

È molto più bello eseguire il debug di un errore di vincolo FK piuttosto che ricostruire un'eliminazione che ha danneggiato la tua applicazione.


4

Sono importanti, perché la tua applicazione non è l'unico modo in cui i dati possono essere manipolati nel database. La tua applicazione può gestire l'integrità referenziale onestamente come vuole, ma tutto ciò che serve è un bozo con i privilegi giusti per venire avanti ed emettere un comando di inserimento, eliminazione o aggiornamento a livello di database e tutta l'applicazione dell'integrità referenziale dell'applicazione viene bypassata. Mettere i vincoli FK a livello di database significa che, a meno che questo bozo scelga di disabilitare il vincolo FK prima di emettere il loro comando, il vincolo FK farà fallire una cattiva istruzione di inserimento / aggiornamento / cancellazione con una violazione dell'integrità referenziale.


3

Ci penso in termini di costi / benefici ... In MySQL , l'aggiunta di un vincolo è una singola riga aggiuntiva di DDL . Sono solo una manciata di parole chiave e un paio di secondi di riflessione. Questo è l'unico "costo" secondo me ...

Gli strumenti amano le chiavi esterne. Le chiavi esterne impediscono dati non validi (ovvero righe orfane) che potrebbero non influire sulla logica o sulla funzionalità di business e quindi passare inosservati e accumularsi. Impedisce inoltre agli sviluppatori che non hanno familiarità con lo schema di implementare interi blocchi di lavoro senza rendersi conto che manca una relazione. Forse tutto è fantastico nell'ambito della tua attuale applicazione, ma se ti sei perso qualcosa e un giorno viene aggiunto qualcosa di inaspettato (pensa a rapporti fantasiosi), potresti essere in un punto in cui devi ripulire manualmente i dati errati che si sono accumulati sin dall'inizio dello schema senza un controllo forzato del database.

Il poco tempo necessario per codificare ciò che è già nella tua testa quando metti insieme le cose potrebbe salvare te o qualcun altro un mucchio di dolore mesi o anni lungo la strada.

La domanda:

Esistono altri usi per le chiavi esterne? Mi manca qualcosa qui?

È un po 'carico. Inserisci commenti, rientri o nomi di variabili al posto di "chiavi esterne" ... Se hai già capito perfettamente la cosa in questione, è "inutile" per te.


2

Riduzione dell'entropia. Ridurre la possibilità che si verifichino scenari caotici nel database. Abbiamo un momento difficile perché sta considerando tutte le possibilità, quindi, a mio parere, la riduzione dell'entropia è la chiave per il mantenimento di qualsiasi sistema.

Quando facciamo un'ipotesi, ad esempio: ogni ordine ha un cliente che l'ipotesi dovrebbe essere applicata da qualcosa . Nei database quel "qualcosa" è chiavi esterne.

Penso che questo valga il compromesso in termini di velocità di sviluppo. Certo, puoi programmare più velocemente senza di loro e questo è probabilmente il motivo per cui alcune persone non li usano. Personalmente ho ucciso un certo numero di ore con NHibernate e qualche vincolo di chiave esterna che si arrabbia quando eseguo qualche operazione. TUTTAVIA, so qual è il problema quindi è meno di un problema. Sto usando strumenti normali e ci sono risorse che mi aiutano a risolvere questo problema, forse anche persone che possono aiutare!

L'alternativa è consentire a un bug di insinuarsi nel sistema (e dato abbastanza tempo, lo farà) dove una chiave esterna non è impostata ei dati diventano incoerenti. Quindi, ricevi una segnalazione di bug insolita, indaga e "OH". Il database è fottuto. Quanto tempo ci vorrà per risolverlo?


1

Puoi visualizzare le chiavi esterne come un vincolo che,

  • Aiuta a mantenere l'integrità dei dati
  • Mostra come i dati sono correlati tra loro (che può aiutare a far rispettare la logica e le regole aziendali)
  • Se utilizzato correttamente, può aiutare ad aumentare l'efficienza con cui i dati vengono recuperati dalle tabelle.

1

Al momento non utilizziamo chiavi esterne. E per la maggior parte non ce ne pentiamo.

Detto questo, è probabile che inizieremo a usarli molto di più nel prossimo futuro per diversi motivi, entrambi per motivi simili:

  1. Diagrammi. È molto più semplice produrre un diagramma di un database se ci sono relazioni di chiavi esterne utilizzate correttamente.

  2. Supporto dello strumento. È molto più semplice creare modelli di dati utilizzando Visual Studio 2008 che può essere utilizzato per LINQ to SQL se sono presenti relazioni di chiavi esterne appropriate.

Quindi immagino che il punto sia che abbiamo scoperto che se stiamo facendo molto lavoro SQL manuale (costruisci query, esegui query, blahblahblah) le chiavi esterne non sono necessariamente essenziali. Una volta che inizi a utilizzare gli strumenti, però, diventano molto più utili.


1
Lavoro su sistemi che non li utilizzano. E me ne pento regolarmente. Ho visto più casi in cui posso contare di dati non sensati che sarebbero stati impediti da vincoli adeguati.
ricorsivo

E avendo lavorato con chiavi esterne al nostro progetto attuale per quasi sei mesi, sono totalmente d'accordo con questo commento.
John Christensen,

1

La cosa migliore dei vincoli di chiave esterna (e dei vincoli in generale, in realtà) è che puoi fare affidamento su di essi quando scrivi le tue query. Molte query possono diventare molto più complicate se non puoi fare affidamento sul fatto che il modello di dati sia "vero".

Nel codice, in genere si ottiene solo un'eccezione da qualche parte, ma in SQL , in genere si ottengono solo le risposte "sbagliate".

In teoria, SQL Server potrebbe utilizzare i vincoli come parte di un piano di query, ma ad eccezione dei vincoli di controllo per il partizionamento, non posso dire di averlo mai effettivamente assistito.


I vincoli di unicità indicano un'elevata cardinalità che viene utilizzata dall'ottimizzatore nella selezione di un meccanismo di join.
Peter ha vinto il

1

Le chiavi esterne non erano mai state esplicite (tabella RIFERIMENTI CHIAVE ESTERE (colonna)) dichiarate nei progetti (applicazioni aziendali e siti di social networking) su cui ho lavorato.

Ma c'è sempre stata una sorta di convenzione per denominare le colonne che erano chiavi esterne.

È come con la normalizzazione del database : devi sapere cosa stai facendo e quali sono le conseguenze di ciò (principalmente le prestazioni).

Sono consapevole dei vantaggi delle chiavi esterne (integrità dei dati, indice per la colonna della chiave esterna, strumenti consapevoli dello schema del database), ma ho anche paura di usare chiavi esterne come regola generale.

Inoltre, vari motori di database potrebbero servire chiavi esterne in modo diverso, il che potrebbe portare a piccoli bug durante la migrazione.

La rimozione di tutti gli ordini e le fatture del cliente eliminato con ON DELETE CASCADE è l'esempio perfetto di schema di database dall'aspetto piacevole, ma progettato in modo errato.


0

Sì. ON DELETE [RESTRICT | CASCADE] impedisce agli sviluppatori di raggruppare i dati, mantenendoli puliti. Recentemente sono entrato a far parte di un team di sviluppatori Rails che non si sono concentrati sui vincoli del database come le chiavi esterne.

Fortunatamente, ho trovato questi: http://www.redhillonrails.org/foreign_key_associations.html - I plug-in RedHill su Ruby on Rails generano chiavi esterne usando la convenzione sullo stile di configurazione . Una migrazione con product_id creerà una chiave esterna per l' ID nella tabella dei prodotti .

Dai un'occhiata agli altri fantastici plug-in di RedHill , comprese le migrazioni incluse nelle transazioni.


0

Se prevedi di generare il tuo codice di accesso ai dati, ovvero Entity Framework o qualsiasi altro ORM, perdi completamente la capacità di generare un modello gerarchico senza chiavi esterne

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.