Cosa c'è che non va nelle chiavi esterne?


259

Ricordo di aver sentito Joel Spolsky menzionare nel podcast 014 che non aveva quasi mai usato una chiave esterna (se ricordo bene). Tuttavia, a me sembrano piuttosto vitali per evitare duplicazioni e conseguenti problemi di integrità dei dati in tutto il database.

Le persone hanno solide ragioni sul perché (per evitare una discussione in linea con i principi Stack Overflow)?

Modifica: "Devo ancora avere un motivo per creare una chiave esterna, quindi questa potrebbe essere la mia prima ragione per crearne effettivamente una".


9
Non penso che Joel non usi gli FK, è solo che non li fa applicare al database. Logicamente, sono ancora FK!
Daren Thomas,

6
Dice che non usa le chiavi esterne, ma concordo con Daren sul fatto che ciò che intende dire è che non usa VINCOLI per le chiavi esterne. Una colonna in una tabella i cui valori dovrebbero essere presi dalla chiave primaria / unica di un'altra tabella SONO chiavi esterne, indipendentemente dal fatto che si aggiunga o meno il vincolo.
Tony Andrews,

22
... Generalmente è sciocco non aggiungere il vincolo: ASSICURA l'integrità in ogni momento, anche se c'è un bug nel codice dell'applicazione o se stai lavorando dietro le quinte facendo una "correzione" di dati.
Tony Andrews,

2
+1 Per il commento di Tony. C'è troppa confusione tra la funzionalità e il concetto logico di chiavi esterne là fuori.
JohnFx,

4
@DanMan, non so dove hai guadagnato l'impressione, credo. In realtà dico sopra "Generalmente è sciocco non aggiungere il vincolo: ASSICURA l'integrità in ogni momento"
Tony Andrews,

Risposte:


352

Motivi per utilizzare le chiavi esterne:

  • non otterrai Orphaned Rows
  • puoi ottenere un buon comportamento "all'eliminazione della cascata", ripulendo automaticamente le tabelle
  • la conoscenza delle relazioni tra le tabelle nel database consente all'ottimizzatore di pianificare le query per l'esecuzione più efficiente, poiché è in grado di ottenere stime migliori sulla cardinalità di join.
  • Gli FK danno un suggerimento piuttosto grande su quali statistiche sono più importanti da raccogliere nel database, il che a sua volta porta a prestazioni migliori
  • abilitano tutti i tipi di supporto generato automaticamente: gli ORM possono generarsi da soli, gli strumenti di visualizzazione saranno in grado di creare layout di schemi piacevoli per te, ecc.
  • qualcuno di nuovo al progetto entrerà nel flusso delle cose più velocemente poiché altrimenti le relazioni implicite sono esplicitamente documentate

Motivi per non utilizzare le chiavi esterne:

  • stai facendo funzionare il DB extra su ogni operazione CRUD perché deve verificare la coerenza FK. Questo può essere un grande costo se hai un sacco di abbandono
  • applicando le relazioni, gli FK specificano un ordine in cui è necessario aggiungere / eliminare elementi, il che può portare al rifiuto da parte del DB di fare ciò che si desidera. (Concesso, in questi casi, quello che stai cercando di fare è creare una fila orfana, e di solito non è una buona cosa). Ciò è particolarmente doloroso quando si eseguono grandi aggiornamenti batch e si carica una tabella prima di un'altra, con la seconda tabella che crea uno stato coerente (ma si dovrebbe fare quel genere di cose se c'è la possibilità che il secondo caricamento fallisca e il il database è ora incoerente?).
  • a volte sai in anticipo che i tuoi dati saranno sporchi, lo accetti e vuoi che il DB lo accetti
  • stai solo diventando pigro :-)

Penso (non sono sicuro!) Che la maggior parte dei database stabiliti fornisca un modo per specificare una chiave esterna che non viene applicata ed è semplicemente un po 'di metadati. Poiché la mancata applicazione cancella tutti i motivi per non utilizzare gli FK, probabilmente dovresti seguire questa strada se si applica uno dei motivi nella seconda sezione.


12
Buona lista! I DBM non controlleranno la coerenza per la parte "R" di CRUD, quindi eliminerei quella parte. Inoltre, è probabilmente un lavaggio perché nella tua app fai la stessa cosa che fa il DBMS: controllerai e ti assicurerai che l'ID padre sia valido prima di CRD e che sia effettivamente più lento di farlo con i DBM!
Matt Rogish,

6
Cosa succede se qualcuno elimina il genitore mentre stai inserendo dei figli? In questo momento quando invio "aggiungi commento" - se hai già eliminato la tua risposta, questo commento è ora orfano. Gli FK l'avrebbero impedito. Inoltre, potrei semplicemente cambiare il parentID per essere tutto ciò che voglio. Qualcuno deve controllare. :)
Matt Rogish,

7
Precisamente, dovrebbe essere il lavoro del DB, poiché è l'unico in grado di garantire la transitabilità di fronte a più client simultanei.
SquareCog,

3
+1 Risposta eccellente: si potrebbe pensare alla seconda ragione per non usare i vincoli FK "rende più difficile rompere la coerenza" che suona davvero come una cosa buona !
Bill Karwin,

9
I vantaggi dell'utilizzo di chiavi esterne FAR superano qualsiasi vantaggio derivante dal non usarli a mio avviso.
Nick Bedford,

80

Questo è un problema di educazione. Se da qualche parte nella tua carriera educativa o professionale hai trascorso del tempo a nutrire e curare database (o hai lavorato a stretto contatto con persone di talento che lo hanno fatto), allora i principi fondamentali di entità e relazioni sono ben radicati nel tuo processo di pensiero. Tra questi rudimenti c'è come / quando / perché specificare le chiavi nel tuo database (primario, esterno e forse alternativo). È una seconda natura.

Se, tuttavia, non hai avuto un'esperienza così approfondita o positiva nel tuo passato con attività legate a RDBMS, allora probabilmente non sei stato esposto a tali informazioni. O forse il tuo passato include l'immersione in un ambiente che è stato anti-database (ad esempio, "quei DBA sono idioti - noi pochi, abbiamo scelto pochi slinger con codice java / c # salveranno il giorno"), nel qual caso potresti essere opposto con veemenza ai borbottii arcani di alcuni dweeb che ti dicono che gli FK (e i vincoli che possono implicare) sono davvero importanti se solo ascoltassi.

La maggior parte di tutti ha imparato quando erano bambini che era importante lavarsi i denti. Puoi cavartela senza di essa? Certo, ma da qualche parte lungo la linea avrai meno denti disponibili di quanto potresti avere se ti fossi lavato dopo ogni pasto. Se mamme e papà fossero abbastanza responsabili da coprire la progettazione del database e l'igiene orale, non avremmo questa conversazione. :-)


61
Userò

5
Personalmente trovo che i principi di RDBMS siano molto più semplici e ben definiti rispetto a quelli dell'igiene orale
Ali Gangji,

Dieci anni in futuro, parlerò sicuramente della progettazione di questo database con mio figlio / a, così lui / lei non sbaglierà e finirà per essere il motivo del prossimo crash di Wall Street a causa di un problema del database.
VarunAgw,

52

Sono sicuro che ci sono molte applicazioni in cui puoi farcela, ma non è la migliore idea. Non puoi sempre contare sulla tua applicazione per gestire correttamente il tuo database e, francamente, la gestione del database non dovrebbe essere di grande preoccupazione per la tua applicazione.

Se stai usando un database relazionale, allora sembra che tu debba avere delle relazioni definite in esso. Sfortunatamente questo atteggiamento (non hai bisogno di chiavi esterne) sembra essere abbracciato da molti sviluppatori di applicazioni che preferiscono non essere disturbati da cose sciocche come l'integrità dei dati (ma è necessario perché le loro aziende non hanno sviluppatori di database dedicati). Di solito nei database messi insieme da questi tipi sei fortunato solo ad avere le chiavi primarie;)


26
Davvero non ho persone che non hanno FK nel loro database. L'ultima volta che ho lavorato con qualcuno che non ce l'aveva, ha detto "no, lo applichiamo nell'applicazione". Tranne che ho fatto un sondaggio su tutti i database dei clienti e ho scoperto che molti di loro avevano orfani ...
ErikE

1
Questo di solito sembra essere il caso. Penso che potresti farcela applicando SOLO nel database (purché i tuoi utenti non si preoccupino delle eccezioni di runtime) ma avere entrambi è davvero l'unica strada da percorrere.
AlexCuse,

È tutto nelle trascrizioni / nella risposta di Atwood "Atwood: ... basato sulle chiavi esterne che hai impostato negli indici, lo capiscono ... Spolsky: [ride] Supponendo che tu lo faccia. Atwood: Beh, supponendo che hai impostato correttamente il tuo database ... "
MemeDeveloper

4
Il database non è chiamato relazionale a causa delle relazioni tra le tabelle (OGNI tipo di database ha un qualche tipo di relazione tra entità!), Ma perché le tabelle stesse sono relazioni , in termini matematici. Vedi Wikipedia .
Massimiliano Kraus,

41

Le chiavi esterne sono essenziali per qualsiasi modello di database relazionale.


54
Il modello, sì. L'implementazione, non essenziale, è probabilmente utile.
dkretz,

4
Siamo spiacenti, ma il motivo principale per cui gli sviluppatori di app non utilizzano i sistemi di gestione di database di oggetti (ovvero database NoSQL!) Più ampiamente è a causa dell'investimento in RDBMS. Il più delle volte il database (non il sistema di gestione del database) è un modello a oggetti di livello intermedio che spesso coinvolge cache distribuite. Questo è dove la cancellazione a cascata, la proprietà e la sincronizzazione delle modifiche devono comunque avvenire. L'RDBMS viene utilizzato principalmente per la persistenza di questo modello di oggetti, e di solito dopo un attento e rigoroso esercizio ORM. I modelli di relazione non sono quasi sempre necessari!
Sentinel,

2
no, le chiavi esterne non sono obbligatorie per indicare "relazionale"
Silver Moon,

Questo non spiega molto.
Nae,

29

Li uso sempre, ma poi realizzo database per sistemi finanziari. Il database è la parte critica dell'applicazione. Se i dati in un database finanziario non sono del tutto precisi, non importa davvero quanto sforzo fai nel tuo progetto di codice / front-end. Stai solo perdendo tempo.

C'è anche il fatto che più sistemi generalmente devono interfacciarsi direttamente con il database - da altri sistemi che leggono i dati (Crystal Reports) a sistemi che inseriscono dati (non necessariamente utilizzando un'API che ho progettato; potrebbe essere scritto da un manager sordo che ha appena scoperto VBScript e ha la password SA per la casella SQL). Se il database non è a prova di idiota come può essere, ciao ciao database.

Se i tuoi dati sono importanti, allora sì, usa le chiavi esterne, crea una suite di procedure memorizzate per interagire con i dati e crea il DB più difficile che puoi. Se i tuoi dati non sono importanti, perché stai creando un database?


2
Bella intuizione. Direi che i dati sono così importanti per ogni applicazione che viene effettivamente utilizzata. L'unica cosa che differisce sono le conseguenze dei dati corrotti. Sono alti per il tuo tipo di app ...
Jay Godse,

20

Aggiornamento : ora uso sempre chiavi esterne. La mia risposta all'obiezione "complicano i test" è "scrivere i test delle unità in modo che non necessitino affatto del database. Tutti i test che utilizzano il database devono utilizzarlo correttamente e che includono chiavi esterne. Se l'installazione è dolorosa, trova un modo meno doloroso per eseguire l'installazione ".


Le chiavi esterne complicano i test automatizzati

Supponiamo che tu stia usando chiavi esterne. Stai scrivendo un test automatizzato che dice "quando aggiorno un conto finanziario, dovrebbe salvare un record della transazione". In questo test, ti occupi solo di due tabelle: accountse transactions.

Tuttavia, accountsha una chiave esterna per contracts, e contractsha un fk per clients, e clientsha un fk per citiese citiesha un fk per states.

Ora il database non ti consentirà di eseguire il test senza impostare i dati in quattro tabelle non correlate al test .

Ci sono almeno due possibili prospettive su questo:

  • "Questa è una buona cosa: il test dovrebbe essere realistico e quei vincoli di dati esisteranno nella produzione."
  • "È una brutta cosa: dovresti essere in grado di riunire i pezzi di prova del sistema senza coinvolgere altri pezzi. Puoi aggiungere test di integrazione per il sistema nel suo insieme."

Potrebbe anche essere possibile disattivare temporaneamente i controlli delle chiavi esterne durante l'esecuzione dei test. MySQL, almeno, lo supporta .


Mi trovo di solito a fare il percorso intermedio qui: uso FK, quindi scrivo metodi di supporto unit test che impostano il DB per supportare vari scenari di test, ad esempio un metodo di supporto per popolare "città" e "stati" per qualsiasi test che necessitano di quelle tabelle popolate.
joelpt

Forse avresti dovuto usare le tabelle dei collegamenti tra le entità non correlate. Oppure vai oltre - DBS separato: considera la situazione in un'architettura orientata ai servizi, o microservizio, in cui ogni elemento (clienti, conti, transazioni) sono sistemi diversi, con DB diversi. Nessun FK tra di loro come tutti. In questo caso, gli FK devono essere utilizzati per prevenire i dati orfani nelle tabelle secondarie per ciascun tipo di dati.
JeeBee,

3
Ci sono anche DBMS che permettono di vincoli per differita in modo che essi vengono controllati solo quando si commettono l'intera transazione, per cui l'ordine di inserimento, aggiornamento, eliminazione non importa
a_horse_with_no_name

2
Se si sta testando un aggiornamento da un livello aziendale, nell'ambiente di sviluppo dovrebbe essere presente l'FK. Quando si aggiorna il record, è necessario disporre dei valori delle colonne necessari per l'aggiornamento. Altrimenti, IMHO il tuo test non è valido.
KeyOfJ,

3
Il tuo database non dovrebbe nemmeno essere coinvolto nei tuoi test unitari, dovresti prenderli in giro. Durante i test di integrazione sarebbero coinvolti, ma qualsiasi problema dovuto a chiavi esterne è qualcosa in cui anche i tuoi utenti si imbatteranno a meno che tu non lo risolva.
Andreas Bergström,

16

"Possono rendere più ingombrante la cancellazione dei record - non è possibile eliminare il record" principale "dove ci sono record in altre tabelle in cui le chiavi esterne violerebbero quel vincolo."

È importante ricordare che lo standard SQL definisce le azioni che vengono eseguite quando una chiave esterna viene eliminata o aggiornata. Quelli che conosco sono:

  • ON DELETE RESTRICT- Impedisce l'eliminazione di tutte le righe nell'altra tabella che dispongono di chiavi in ​​questa colonna. Questo è ciò che Ken Ray ha descritto sopra.
  • ON DELETE CASCADE - Se viene eliminata una riga nell'altra tabella, eliminare eventuali righe in questa tabella che fanno riferimento a essa.
  • ON DELETE SET DEFAULT - Se viene eliminata una riga nell'altra tabella, impostare eventuali chiavi esterne che fanno riferimento al valore predefinito della colonna.
  • ON DELETE SET NULL - Se viene eliminata una riga nell'altra tabella, impostare su null tutte le chiavi esterne che fanno riferimento in questa tabella.
  • ON DELETE NO ACTION- Questa chiave esterna indica solo che è una chiave esterna; vale a dire per l'uso in mappatori OR.

Queste stesse azioni si applicano anche a ON UPDATE.

L'impostazione predefinita sembra dipendere da quale server che stai utilizzando.


14

@imphasing - questo è esattamente il tipo di mentalità che provoca incubi di manutenzione.

Perché oh perché dovresti ignorare l'integrità referenziale dichiarativa, in cui i dati possono essere garantiti almeno coerenti, a favore della cosiddetta "applicazione del software" che è una debole misura preventiva nella migliore delle ipotesi.


Perché gli sviluppatori coinvolti non hanno mai affrontato un problema che richiede un modello relazionale non banale, normalizzato. Molti problemi non lo fanno, in particolare il tipo che abbonda nella programmazione di tipo web / "social media" che è tutta la mania oggi. Se tutto ciò che deriva dal back-end di un framework ORM soddisfa il problema in alfa, è improbabile che qualcuno pensi molto di più alla modellazione dei dati. Molti di questi problemi sono gestiti altrettanto facilmente da negozi K / V, database di documenti o serializzazione diretta di oggetti.
zxq9,

12

C'è un buon motivo per non usarli: se non capisci il loro ruolo o come usarli.

Nelle situazioni sbagliate, i vincoli delle chiavi esterne possono portare alla replica a cascata degli incidenti. Se qualcuno rimuove il record sbagliato, annullarlo può diventare un compito enorme.

Inoltre, al contrario, quando è necessario rimuovere qualcosa, se mal progettato, i vincoli possono causare tutti i tipi di blocchi che ti impediscono.


8
L'eliminazione di una riga in produzione senza backup non è un argomento valido. Se non li capisci, dovresti considerare di impararlo invece di ometterlo.
Guillaume,

2
@Guillaume Penso che la sua risposta sia stata un po 'sarcastica, da non prendere alla lettera: se non le capisci, non le usi. Ma ovviamente dovresti comprenderli e usarli entrambi.
Benjamin,

^ Questo. Sono strumenti utili, ma nelle mani di un principiante, sono strumenti pericolosi.
Kent Fredric,

11

Non ci sono buoni motivi per non usarli ... a meno che le file orfane non siano un grosso problema per te, immagino.


11
Perché le file orfane sono un grosso problema?
Seun Osewa,

2
Che dire del multithreading? Possono causare un incubo multithreading in determinate situazioni. In un'applicazione complessa con più thread che scrivono il database che potrebbe incontrare oggetti che devono fare riferimento l'un l'altro, è meglio controllare l'integrità referenziale nella logica aziendale, in particolare se le tabelle diventeranno statiche in seguito.
Keith Pinson,

Sono d'accordo. Inoltre, preferisco avere file opane che posso recuperare più tardi nel tempo, piuttosto che scartarle senza pietà.
PedroD,

4

La domanda più grande è: guideresti con una benda sugli occhi? È così se si sviluppa un sistema senza vincoli referenziali. Tenere presente che cambiano i requisiti aziendali, le modifiche alla progettazione delle applicazioni, i rispettivi presupposti logici nelle modifiche al codice, la logica stessa può essere riformattata e così via. In generale, i vincoli nei database sono posti sotto ipotesi logiche contemporanee, apparentemente corrette per particolari serie di asserzioni e ipotesi logiche.

Attraverso il ciclo di vita di un'applicazione, i controlli referenziali e dei dati limitano la raccolta dei dati di polizia tramite l'applicazione, soprattutto quando i nuovi requisiti guidano i cambiamenti logici dell'applicazione.

Per quanto riguarda questo elenco , una chiave esterna non "da sola" migliora le prestazioni, né "degrada le prestazioni" in modo significativo dal punto di vista del sistema di elaborazione delle transazioni in tempo reale. Tuttavia, esiste un costo aggregato per il controllo dei vincoli nel sistema "batch" di volume elevato. Quindi, ecco la differenza, in tempo reale rispetto al processo di transazione batch; elaborazione in batch: laddove il costo aumentato, indotto da controlli di vincolo, di un batch elaborato in sequenza rappresenti un successo in termini di prestazioni.

In un sistema ben progettato, i controlli di coerenza dei dati verrebbero eseguiti "prima" dell'elaborazione di un batch (tuttavia, vi è anche un costo associato qui); pertanto, i controlli dei vincoli di chiave esterna non sono richiesti durante il tempo di caricamento. In effetti tutti i vincoli, inclusa la chiave esterna, devono essere temporaneamente disabilitati fino a quando il batch non viene elaborato.

PRESTAZIONI QUERY : se le tabelle sono unite su chiavi esterne, tenere presente che le colonne di chiavi esterne NON SONO INDICATE (sebbene la rispettiva chiave primaria sia indicizzata per definizione). Indicizzando una chiave esterna, del resto, indicizzando qualsiasi chiave e unendo le tabelle su indicizzate aiuta a ottenere prestazioni migliori, non unendo una chiave non indicizzata con vincolo di chiave esterna su di essa.

Cambiando argomento , se un database supporta solo la visualizzazione di un sito Web / rendering di contenuti / ecc. E registra i clic, un database con vincoli completi su tutte le tabelle viene eliminato per tali scopi. Pensaci. La maggior parte dei siti Web non utilizza nemmeno un database per tale. Per requisiti simili, in cui i dati vengono appena registrati e non citati per esempio, utilizzare un database in memoria, che non ha vincoli. Ciò non significa che non esiste un modello di dati, un modello logico sì, ma nessun modello di dati fisici.


Bene, non so perché inserire 3 doppie righe al posto di spazi vuoti e cambiare due parole contenga come "67% è Jonathan Leffler", ma non credo di aver fatto nulla di simile su quel lavoro. Il testo principale è stato fornito da @jay (utente 183837).
Jonathan Leffler,

Ho solo supposto che i paragrafi non funzionassero qui, come nel caso della maggior parte degli altri siti. Quindi, ho messo tutto come uno, usando gli grassetti per il cambio di flusso.
Jasbir L

3

Motivo aggiuntivo per l'utilizzo di chiavi esterne: - Consente un maggiore riutilizzo di un database

Motivo aggiuntivo per NON utilizzare chiavi esterne: - Si sta tentando di bloccare un cliente nello strumento riducendo il riutilizzo.


3

Dalla mia esperienza è sempre meglio evitare di utilizzare gli FK nelle applicazioni critiche del database. Non sarei in disaccordo con i ragazzi qui che affermano che gli FK sono una buona pratica ma non è pratico dove il database è enorme e ha enormi operazioni CRUD / sec. Posso condividere senza nominare ... una delle maggiori banche di investimento di non ha un singolo FK nei database. Questi vincoli vengono gestiti dai programmatori durante la creazione di applicazioni che coinvolgono DB. Il motivo di base è che ogni volta che viene fatto un nuovo CRUD deve effettuare più tabelle e verificare per ogni inserimento / aggiornamento, anche se questo non sarà un grosso problema per le query che riguardano singole righe ma crea una latenza enorme quando si ha a che fare con elaborazione in batch che ogni grande banca deve svolgere come attività quotidiane.

È meglio evitare gli FK ma il suo rischio deve essere gestito dai programmatori.


8
Non credo che le pratiche di sviluppo presso le grandi banche stabiliscano lo standard d'oro.
Adriaan Koster,

3

"Prima di aggiungere un record, verificare che esista un record corrispondente in un'altra tabella" è la logica aziendale.

Ecco alcuni motivi per cui non lo desideri nel database:

  1. Se le regole aziendali cambiano, è necessario modificare il database. Il database dovrà ricreare l'indice in molti casi e questo è lento su tabelle di grandi dimensioni. (Le modifiche alle regole includono: consentire agli ospiti di pubblicare messaggi o consentire agli utenti di eliminare il proprio account nonostante abbiano pubblicato commenti, ecc.).

  2. Modificare il database non è facile come distribuire una correzione software spingendo le modifiche al repository di produzione. Vogliamo evitare di modificare il più possibile la struttura del database. Maggiore è la logica aziendale presente nel database, maggiore è la possibilità di modificare le banche dati (e di attivare la reindicizzazione).

  3. TDD. Nei test unitari è possibile sostituire il database con simulazioni e testarne la funzionalità. Se si dispone di una logica aziendale nel database, non si stanno eseguendo test completi e sarebbe necessario testare con il database o replicare la logica aziendale nel codice a scopo di test, duplicando la logica e aumentando la probabilità che la logica non funzioni nel stessa strada.

  4. Riutilizzare la logica con diverse origini dati. Se non esiste alcuna logica nel database, la mia applicazione può creare oggetti dai record del database, crearli da un servizio Web, un file JSON o qualsiasi altra fonte. Devo solo scambiare l'implementazione del mapper dati e posso usare tutta la mia logica aziendale con qualsiasi fonte. Se nel database è presente la logica, ciò non è possibile e è necessario implementare la logica a livello di mappatore dati o nella logica aziendale. Ad ogni modo, hai bisogno di quei controlli nel tuo codice. Se nel database non è presente alcuna logica, è possibile distribuire l'applicazione in posizioni diverse utilizzando database o implementazioni di file flat diversi.


2

Concordo con le risposte precedenti in quanto sono utili per mantenere la coerenza dei dati. Tuttavia, alcune settimane fa c'è stato un post interessante di Jeff Atwood che parlava dei pro e dei contro di dati normalizzati e coerenti.

In poche parole, un database denormalizzato può essere più veloce quando si gestiscono enormi quantità di dati; e potresti non preoccuparti della coerenza precisa a seconda dell'applicazione, ma ti costringe a stare molto più attento quando gestisci i dati, poiché il DB non lo sarà.


Jeff fa alcuni punti positivi. Tuttavia, Dan Chak in "Enterprise Rails" mostra un modo per progettare tabelle cache che sono essenzialmente una copia non normalizzata dei dati. Le query vengono eseguite rapidamente e se la tabella non deve essere aggiornata, funziona bene. Trovo che se i tuoi dati guidano il comportamento (ad esempio lo stato dell'applicazione) della tua applicazione, hai bisogno che i dati siano normalizzati il ​​più possibile perché dati altrimenti incoerenti portano a comportamenti incoerenti dell'applicazione.
Jay Godse,

Un data warehouse denormalizzato può essere utile quando si leggono grandi volumi di dati su percorsi di accesso coerenti e previsti . In tutti gli altri scenari, questo è un errore pericoloso.
Peter Wone,

2

Il database Clarify è un esempio di un database commerciale che non ha chiavi primarie o esterne.

http://www.geekinterview.com/question_details/18869

La cosa divertente è che la documentazione tecnica fa di tutto per spiegare come le tabelle sono correlate, quali colonne usare per unirle, ecc.

In altre parole, avrebbero potuto unire le tabelle con dichiarazioni esplicite (DRI) ma hanno scelto di non farlo .

Di conseguenza, il database Clarify è pieno di incoerenze e sottoperforma.

Ma suppongo che abbia semplificato il lavoro degli sviluppatori, non dover scrivere codice per gestire l'integrità referenziale come controllare le righe correlate prima di eliminare, aggiungere.

E questo, penso, è il vantaggio principale di non avere vincoli di chiave esterna in un database relazionale. Lo rende più facile da sviluppare, almeno dal punto di vista del diavolo.


Il codice per gestire un controllo di integrità referenziale non riuscito è molto più piccolo del codice per gestire dati incoerenti.
Jay Godse,

@Jay d'accordo! Non pensare che sto sostenendo questo approccio.
Ed Guiness,

2

Conosco solo database Oracle, nessun altro, e posso dire che le chiavi esterne sono essenziali per mantenere l'integrità dei dati. Prima di inserire i dati, è necessario creare una struttura di dati e renderli corretti. Quando ciò viene fatto - e quindi vengono create tutte le chiavi primarie E esterne - il lavoro è fatto!

Significato: file orfane? No. Non l'ho mai visto in vita mia. A meno che un cattivo programmatore non abbia dimenticato la chiave esterna o se l'ha implementata su un altro livello. Entrambi sono - nel contesto di Oracle - enormi errori, che porteranno alla duplicazione dei dati, dati orfani e quindi: corruzione dei dati. Non riesco a immaginare un database senza l'applicazione dell'FK. Mi sembra il caos. È un po 'come il sistema di permessi Unix: immagina che tutti siano root. Pensa al caos.

Le chiavi esterne sono essenziali, proprio come le chiavi primarie. È come dire: e se rimuovessimo le chiavi primarie? Bene, il caos totale sta per accadere. Questo è quello che. Non è possibile spostare la responsabilità della chiave primaria o esterna a livello di programmazione, deve essere a livello di dati.

Svantaggi? Si assolutamente ! Perché su insert, accadranno molti più controlli. Ma, se l'integrità dei dati è più importante delle prestazioni, è un gioco da ragazzi. Il problema con le prestazioni su Oracle è più legato agli indici, che vengono forniti con PK e FK.


1

Possono rendere più ingombrante la cancellazione dei record: non è possibile eliminare il record "principale" in cui sono presenti record in altre tabelle in cui le chiavi esterne violerebbero tale vincolo. È possibile utilizzare i trigger per eliminare a cascata.

Se hai scelto la chiave primaria in modo non corretto, la modifica di quel valore diventa ancora più complessa. Ad esempio, se ho il PK della mia tabella "clienti" come nome della persona e faccio di quella chiave un FK nella tabella "ordini", se il cliente vuole cambiare il suo nome, allora è un dolore reale. ma questo è solo un design scadente del database.

Credo che i vantaggi dell'utilizzo delle chiavi Fireign siano superiori a tutti i presunti svantaggi.


5
Tendo comunque a eliminare raramente le cose. Basta contrassegnare un bit "Visibile / attivo".
Dana,

+1 per "Credo che i vantaggi nell'uso delle chiavi di fuoco superino qualsiasi presunto svantaggio"
Ian Boyd,

2
Mai e poi mai cambiare il valore di una chiave primaria. Si elimina l'intera riga e ricreare in modo diverso. Se pensi di doverlo modificare , il tuo schema è difettoso.
DanMan,

Cambiare il nome del cliente non sarebbe affatto un problema se la tua chiave esterna è impostata su CustomerId (PK). nella tabella degli ordini. L'unico modo sarebbe doloroso se l'FK fosse impostato su CustomerName, cosa che non dovrebbe mai accadere. IMHO
KeyOfJ,

1

La verifica dei vincoli delle chiavi esterne richiede un po 'di tempo della CPU, quindi alcune persone omettono le chiavi esterne per ottenere prestazioni extra.


6
Quanto tempo viene impiegato dalla CPU per rimuovere i dati duplicati e incoerenti?
Ed Guiness,

Sì, questo è vero. Su un sistema su cui lavoro dobbiamo inserire 10 - 40 concerti di dati alla volta in un database e le prestazioni dell'FK con e senza sono visibili nel tempo totale necessario.
Paul Mendoza,

1

Ho sentito anche questo argomento - da persone che hanno dimenticato di mettere un indice sulle loro chiavi esterne e poi si sono lamentate del fatto che alcune operazioni erano lente (perché il controllo dei vincoli poteva sfruttare qualsiasi indice). Quindi, per riassumere: non esiste una buona ragione per non usare le chiavi esterne. Tutti i database moderni supportano le eliminazioni in cascata, quindi ...


9
Credo che il vero motivo per cui i vincoli degli FK non sono utilizzati da alcuni (la maggior parte, dal mio punto di vista) è la pura pigrizia con la pretesa che possano difendere la loro pigrizia con la loro discussione sul risparmio delle prestazioni. Sono fermamente convinto che la stragrande maggioranza delle spese di stupidità sostenute dalla nostra azienda sia dovuta alla mancanza di applicazione dei vincoli dell'FK e all'effetto a catena che ciò ha attraverso un'azienda. La mancanza di chiavi uniche è l'altra cosa che mi fa impazzire accanto a oltre 2000 procedure memorizzate di linea con 12 livelli di IF nidificati e rientri casuali, ma mi fermerò ora.
Ciad

1

L'argomento che ho sentito è che il front-end dovrebbe avere queste regole commerciali. Le chiavi esterne "aggiungono un sovraccarico non necessario" quando non dovresti consentire alcun inserimento che rompa i tuoi vincoli in primo luogo. Sono d'accordo con questo? No, ma è quello che ho sempre sentito.

EDIT: La mia ipotesi è che si riferiva a vincoli di chiave esterna , non a chiavi esterne come concetto.


No. Non gli piacciono le chiavi reali!
ljs,

Questo mi stupisce. Esiste una grande differenza tra il mancato gradimento dei vincoli di chiave esterna e il mancato gradimento di chiavi esterne. Non sono sicuro di come tu abbia un database relazionale senza di loro.
lordscarlet,

Sì, sono rimasto scioccato quando l'ho sentito. Tuttavia, avrebbe potuto essere involontariamente ironico; forse pubblicherà qui e chiarirà ad un certo punto :-)
ljs

1

Per me, se si desidera rispettare gli standard ACID , è fondamentale disporre di chiavi esterne per garantire l'integrità referenziale.


1

Devo secondare la maggior parte dei commenti qui, le chiavi esterne sono elementi necessari per garantire che i dati siano integri. Le diverse opzioni di ON DELETE e ON UPDATE ti permetteranno di aggirare alcune delle "cadute" che le persone citano qui riguardo al loro uso.

Trovo che nel 99% di tutti i miei progetti avrò FK per far rispettare l'integrità dei dati, tuttavia ci sono rare occasioni in cui ho clienti che DEVONO conservare i loro vecchi dati, indipendentemente da quanto male sia .... ma poi passo molto tempo a scrivere il codice che entra per ottenere comunque solo i dati validi, quindi diventa inutile.


1

Che ne dite di manutenibilità e costanza nei cicli di vita delle applicazioni? La maggior parte dei dati ha una durata maggiore rispetto alle applicazioni che ne fanno uso. Le relazioni e l'integrità dei dati sono troppo importanti per lasciare alla speranza che il prossimo team di sviluppo ottenga il giusto nel codice dell'app. Se non hai lavorato su un database con dati sporchi che non rispettano le relazioni naturali, lo farai. L'importanza dell'integrità dei dati diventerà quindi molto chiara.


1

Penso anche che le chiavi esterne siano una necessità nella maggior parte dei database. L'unico inconveniente (oltre all'hit prestazionale derivante dall'aver applicato la coerenza) è che avere una chiave esterna consente alle persone di scrivere codice che presuppone l'esistenza di una chiave esterna funzionale. Non dovrebbe mai essere permesso.

Ad esempio, ho visto persone scrivere codice che inserisce nella tabella di riferimento e quindi tenta di inserirli nella tabella di riferimento senza verificare che il primo inserimento abbia avuto esito positivo. Se la chiave esterna viene rimossa in un secondo momento, si ottiene un database incoerente.

Inoltre non hai la possibilità di assumere un comportamento specifico durante l'aggiornamento o l'eliminazione. Devi ancora scrivere il tuo codice per fare quello che vuoi, indipendentemente dal fatto che sia presente una chiave esterna. Se si presume che le eliminazioni siano in cascata quando non lo sono, le eliminazioni falliranno. Se si presume che gli aggiornamenti alle colonne a cui viene fatto riferimento vengano propagati alle righe di riferimento quando non lo sono, gli aggiornamenti falliranno. Ai fini della scrittura del codice, potresti non avere queste funzionalità.

Se queste funzionalità sono attive, il tuo codice le emulerà comunque e perderai un po 'di prestazioni.

Quindi, il riepilogo .... Le chiavi esterne sono essenziali se hai bisogno di un database coerente. Le chiavi esterne non dovrebbero mai essere considerate presenti o funzionali nel codice che scrivi.


1

Mi associo alla risposta di Dmitriy - molto ben messa.

Per coloro che sono preoccupati per il sovraccarico prestazionale che spesso gli FK portano, c'è un modo (in Oracle) che puoi ottenere il vantaggio dell'ottimizzatore di query del vincolo FK senza il sovraccarico di costi della convalida del vincolo durante l'inserimento, l'eliminazione o l'aggiornamento. Cioè per creare il vincolo FK con gli attributi RELY DISABLE NOVALIDATE. Ciò significa che Query Optimizer ASSUME che il vincolo è stato applicato durante la creazione di query, senza che il database lo applichi effettivamente. Devi stare molto attento qui ad assumerti la responsabilità quando popoli una tabella con un vincolo FK come questo per assicurarti assolutamente di non avere dati nelle tue colonne FK che violano il vincolo, come se lo facessi tu potrebbe ottenere risultati inaffidabili da query che coinvolgono la tabella su cui è attivo questo vincolo FK.

Di solito uso questa strategia su alcune tabelle nel mio schema di data mart, ma non nel mio schema di gestione temporanea integrato. Mi assicuro che le tabelle da cui sto copiando i dati abbiano già applicato lo stesso vincolo o che la routine ETL imponga il vincolo.


1

Molte delle persone che rispondono qui sono troppo prese dall'importanza dell'integrità referenziale implementata attraverso vincoli referenziali. Lavorare su grandi database con integrità referenziale non funziona bene. Oracle sembra particolarmente cattivo nelle eliminazioni a cascata. La mia regola empirica è che le applicazioni non dovrebbero mai aggiornare direttamente il database e dovrebbero essere tramite una procedura memorizzata. Ciò mantiene la base di codice all'interno del database e significa che il database mantiene la sua integrità.

Laddove molte applicazioni potrebbero accedere al database, sorgono problemi a causa di vincoli di integrità referenziale, ma ciò dipende da un controllo.

C'è anche un problema più ampio in questo, gli sviluppatori di applicazioni possono avere requisiti molto diversi con i quali gli sviluppatori di database potrebbero non essere così familiari.


5
"le applicazioni non dovrebbero mai aggiornare direttamente il database e dovrebbero essere tramite una procedura memorizzata. Ciò mantiene la base di codice all'interno del database e significa che il database mantiene la sua integrità." <- Qui si presume che la logica nelle procedure memorizzate non possa violare l'integrità dei dati, il che è semplicemente sbagliato.
Tim Gautier,

1

Se sei assolutamente sicuro che l'unico sistema di database sottostante non cambierà in futuro, utilizzerei le chiavi esterne per garantire l'integrità dei dati.

Ma ecco un altro ottimo motivo nella vita reale per non usare affatto le chiavi esterne:

Stai sviluppando un prodotto, che dovrebbe supportare diversi sistemi di database.

Se si lavora con Entity Framework, che è in grado di connettersi a molti sistemi di database diversi, è possibile che si desideri supportare anche database senza server "open-source-free". Non tutti questi database potrebbero supportare le regole della chiave esterna (aggiornamento, eliminazione di righe ...).

Questo può portare a diversi problemi:

1.) È possibile che si verifichino errori durante la creazione o l'aggiornamento della struttura del database. Forse ci saranno solo errori silenziosi, perché le tue chiavi esterne sono semplicemente ignorate dal sistema di database.

2.) Se si fa affidamento su chiavi esterne, si effettueranno probabilmente controlli di integrità dei dati minori o addirittura assenti nella logica aziendale. Ora, se il nuovo sistema di database non supporta queste regole di chiave esterna o si comporta semplicemente in modo diverso, è necessario riscrivere la logica aziendale.

Potresti chiedere: chi ha bisogno di diversi sistemi di database? Bene, non tutti possono permettersi o vogliono un completo SQL Server sulla sua macchina. Questo è un software che deve essere mantenuto. Altri hanno già investito tempo e denaro in alcuni altri sistemi DB. I database senza server sono ideali per i piccoli clienti su una sola macchina.

Nessuno sa come si comportano tutti questi sistemi DB, ma la tua logica aziendale, con i controlli di integrità, rimane sempre la stessa.


0

Ho sempre pensato che fosse pigro non usarli. Mi è stato insegnato che dovrebbe sempre essere fatto. Ma poi, non ho ascoltato la discussione di Joel. Potrebbe aver avuto una buona ragione, non lo so.


Era più un'osservazione fuori dal comune che una discussione, anche se forse dovrei ricercare con precisione ciò che pensa sull'argomento in modo indipendente! Tuttavia, ero curioso dell'opinione della community anche su questo argomento!
ljs,

0

Una volta in cui un FK potrebbe causare un problema è quando si hanno dati storici che fanno riferimento alla chiave (in una tabella di ricerca) anche se non si desidera più la chiave disponibile.
Ovviamente la soluzione è progettare meglio le cose in anticipo, ma sto pensando a situazioni del mondo reale in cui non hai sempre il controllo della soluzione completa.
Ad esempio: forse hai una tabella di ricerca customer_typeche elenca diversi tipi di clienti: supponiamo che devi rimuovere un determinato tipo di cliente, ma (a causa di restrizioni aziendali) non è in grado di aggiornare il software client e nessuno ha nascosto questa situazione durante lo sviluppo del software, il fatto che si tratti di una chiave esterna in un'altra tabella potrebbe impedire di rimuovere la riga anche se si conoscono i dati storici a cui fa riferimento è irrilevante.
Dopo essere stato bruciato con questo alcune volte, probabilmente ti allontani dall'applicazione delle relazioni da parte di db.
(Non sto dicendo che questo è buono - sto solo dando una ragione per cui potresti decidere di evitare FK e db in generale)


Se capisco cosa stai cercando di dire, penso che la mia risposta sarebbe quella di eliminare logicamente il record nella tabella di ricerca o archiviare i dati storici non più rilevanti e archiviare anche il record di ricerca.
Chad,
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.