it-swarm.it

Cosa c'è che non va nelle chiavi esterne?

Ricordo di aver sentito Joel Spolsky menzionare in 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 dei solidi motivi 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 questo potrebbe essere il mio primo motivo per impostarne effettivamente uno. "

247
ljs

Motivi per utilizzare le chiavi esterne:

  • non otterrai Orphaned Rows
  • puoi ottenere un comportamento piacevole "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 un'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, gli strumenti di visualizzazione saranno in grado di creare layout di schemi Nice 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 controllare 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.

344
SquareCog

Questo è un problema di educazione. Se da qualche parte nella tua carriera educativa o professionale hai trascorso del tempo a nutrire e curare i database (o hai lavorato a stretto contatto con persone di talento che lo hanno fatto), allora i principi fondamentali delle entità e delle relazioni sono ben radicati nel tuo processo di pensiero. Tra questi rudimenti c'è come/quando/perché specificare le chiavi nel 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à relative 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 di codice Java/c # salveranno la giornata"), nel qual caso potresti essere opposto con veemenza ai balbettani 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. :-)

79
Ed Lucas

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 dovresti avere alcuni relazioni definiti 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;)

52
AlexCuse

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

40
Galwegian

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 ottuso che ha appena scoperto VBScript e ha la SA per la casella SQL). Se il database non è così a prova di idiota come può essere, beh, 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 per cominciare?

29
Ant

Aggiornamento : ora utilizzo sempre le 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 usarlo 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 automatico che dice "quando aggiorno un conto finanziario, dovrebbe salvare un record della transazione". In questo test, ti occupi solo di due tabelle: accounts e transactions.

Tuttavia, accounts ha una chiave esterna per contracts e contracts ha un fk su clients e clients ha un fk su cities e cities ha un fk in 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 l'intero sistema."

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

19
Nathan Long

"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 con chiavi in ​​questa colonna. Questo è ciò che Ken Ray ha descritto sopra.
  • ON DELETE CASCADE - Se viene eliminata una riga nell'altra tabella, eliminare tutte le 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 OR mapper.

Queste stesse azioni si applicano anche a ON UPDATE.

L'impostazione predefinita sembra dipendere dal server sql che stai utilizzando.

14
Powerlord

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

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

14
Ed Guiness

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 mastodontico.

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

12
Kent Fredric

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

11
Matt Rogish

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 dell'applicazione, 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 determinano cambiamenti logici dell'applicazione.

Nell'argomento di 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 batch: laddove il costo aumentato, sostenuto da controlli di vincolo, di un batch elaborato in sequenza rappresenti un impatto sulle 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.

QUERY PERFORMANCE - se le tabelle sono unite su chiavi esterne, sii consapevole del fatto 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.

Modifica dei soggetti, se un database supporta solo la visualizzazione di siti Web/rendering di contenuti/ecc. E registra clic, quindi 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 questo. 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.

4
jasbir L

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 batch che qualsiasi grande banca deve svolgere come attività quotidiane.

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

3
Rachit

"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 diversi o implementazioni di file flat.

3
Tom B

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

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

3
Dan

Concordo con le risposte precedenti in quanto sono utili per mantenere la coerenza dei dati. Tuttavia, c'è stato un post interessante di Jeff Atwood alcune settimane fa che ha discusso 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à.

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, loro avrebbero potuto aver unito le tabelle con dichiarazioni esplicite (DRI) ma loro hanno scelto di non .

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 quello, 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.

2
Ed Guiness

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 che sia corretta. 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, ai dati orfani e quindi alla corruzione dei dati. Non riesco a immaginare un database senza l'applicazione dell'FK. A me 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.

2
tvCa

Possono rendere più ingombrante la cancellazione dei record: non è possibile eliminare il record "master" 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 nell'uso delle chiavi Fireign siano superiori a tutti i presunti svantaggi.

1
Ken Ray

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ò gli FK per far rispettare l'integrità dei dati, tuttavia ci sono quelle rare occasioni in cui ho clienti che DEVONO conservare i loro vecchi dati, indipendentemente da quanto male ... ma poi passo molto tempo a scrivere il codice che entra per ottenere solo i dati validi, quindi diventa inutile.

1
Mitchel Sellers

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 qualsiasi inserimento che rompa i tuoi vincoli in primo luogo. Sono d'accordo con questo? No, ma è quello che ho sempre sentito.

EDIT: Suppongo che si riferisse a vincoli di chiave esterna , non a chiavi esterne come concetto.

1
lordscarlet

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.

1
remonedo

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. Il database senza server è l'ideale 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.

1
Michael

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
Mike McAllister

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

1
Arno

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

1
CodeRot

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.

1
Zak

Penso anche che le chiavi esterne siano una necessità nella maggior parte dei database. L'unico inconveniente (oltre all'hit prestazionale che deriva 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
Eric

WoWoWo ...
Risposte ovunque. In realtà questo è l'argomento più complicato che abbia mai incontrato. Uso gli FK quando sono necessari, ma nell'ambiente di produzione li uso raramente.

Ecco i miei perché uso raramente gli Fks:

1. Il più delle volte ho a che fare con enormi dati su server di piccole dimensioni per migliorare le prestazioni ho bisogno di rimuovere gli FK. Perché quando si hanno gli FK e si crea, si aggiorna o si cancella l'RDBMS per prima cosa verificare se non vi è alcuna violazione dei vincoli e se si dispone di un DB enorme che potrebbe essere fatale

2. A volte ho bisogno di importare dati da altri luoghi e, poiché non sono troppo sicuro di quanto siano strutturati, ho semplicemente abbandonato gli FK.

3. Nel caso in cui si tratti di più DB e la chiave di riferimento in un altro DB non andrà bene (per ora) fino a quando non si rimuovono gli FK (relazioni tra database)
4. È stato anche un caso in cui hai scritto un'applicazione che si adatterà a qualunque RDBMS o desideri che il tuo DB venga esportato e importato in qualsiasi sistema RDBMS in questo caso ogni specifico sistema RDBMS ha il suo modo di gestire gli FK e probabilmente lo sarai obbligato a rinunciare all'uso di FK.

5. Se utilizzi la piattaforma RDBMS (ORM), sai che alcuni di essi offrono la propria mappatura a seconda della soluzione e della tecnicità della loro offerta e non ti interessa creare le tabelle e i loro FK.

6. Prima dell'ultimo punto ci saranno le conoscenze per gestire DB che ha FK e le conoscenze per scrivere un'applicazione che fa tutto il lavoro senza la necessità di FK 7. Infine, come ho iniziato a dire che tutto dipende dal tuo scenario, nel caso in cui la conoscenza non lo sia una barriera. Avrai sempre voglia di correre il meglio del meglio che puoi ottenere!


Grazie a tutti!

Una volta in cui un FK può 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_type che elenca diversi tipi di clienti: supponiamo che sia necessario rimuovere un determinato tipo di cliente, ma (a causa di restrizioni aziendali) non sono in grado di aggiornare il software client e nessuno ha nascosto questa situazione durante lo sviluppo del software, il fatto che si tratta di una chiave esterna in un'altra tabella che potrebbe impedire di rimuovere la riga anche se si conoscono i dati storici a cui fa riferimento è irrilevante.
Dopo essere stato bruciato alcune volte, probabilmente ti allontani dall'applicazione delle relazioni da parte di db.
(Non sto dicendo che va bene, basta dare una ragione per cui potresti decidere di evitare FK e db in generale)

0
hamishmcn

In un progetto su cui ho lavorato c'erano spesso relazioni implicite piuttosto che esplicite, in modo che numerose tabelle potessero essere unite sulla stessa colonna.

Prendi la seguente tabella

Indirizzo

  • AddressId (PK)
  • EntityID
  • Tipo di entità
  • Città
  • Stato
  • Nazione
  • Eccetera..

I valori possibili di EntityType possono essere Employee, Company, Customer e EntityId si riferisce alla chiave primaria di qualunque tabella ti interessasse.

Non penso davvero che questo sia il modo migliore per fare le cose, ma ha funzionato per questo progetto.

0
Curtis

Come molte cose, è un compromesso. È una domanda su dove si desidera svolgere il lavoro per verificare l'integrità dei dati:

(1) usa una chiave esterna (un singolo punto per configurare una tabella, la funzionalità è già implementata, testata, collaudata per funzionare)

(2) lasciarlo agli utenti del database (possibili più utenti/app che aggiornano le stesse tabelle che significano più potenziali punti di errore e maggiore complessità nei test).

È più efficiente per il database fare (2), più facile da mantenere e meno rischi con (1).

0
Jen A

Farò eco a quello che ha detto Dmitriy, ma aggiungendo un punto.

Ho lavorato su un sistema di fatturazione batch che doveva inserire grandi gruppi di righe su oltre 30 tabelle. Non ci è stato permesso di fare un pump dei dati (Oracle), quindi abbiamo dovuto fare inserimenti di massa. Quei tavoli avevano chiavi esterne, ma ci eravamo già assicurati che non avessero interrotto alcuna relazione.

Prima di inserire, disabilitiamo i vincoli di chiave esterna in modo che Oracle non impieghi per sempre a eseguire gli inserimenti. Dopo che l'inserimento ha esito positivo, riattiviamo i vincoli.

PS: in un database di grandi dimensioni con molte chiavi esterne e dati di righe figlio per un singolo record, a volte le chiavi esterne possono essere errate e potresti voler impedire l'eliminazione a cascata. Per noi nel sistema di fatturazione, ci vorrebbe troppo tempo e sarebbe troppo faticoso per il database se facessimo delle eliminazioni a cascata, quindi contrassegniamo il record come non valido con un campo nella tabella del driver principale (padre).

0
typicalrunt

In DB2, se vengono utilizzati MQT (Materialized Query Tables), i vincoli di chiave esterna sono necessari affinché l'ottimizzatore scelga il piano giusto per una determinata query. Poiché contengono le informazioni sulla cardinalità, l'ottimizzatore utilizza pesantemente i metadati per utilizzare un MQT o meno.

0
Senthil

Un buon principio di progettazione della struttura dei dati è garantire che ogni attributo di una tabella o di un oggetto sia soggetto a un vincolo ben compreso. Questo è importante perché se tu o il tuo programma potete contare su dati validi nel database, avrete meno probabilità di avere difetti del programma causati da dati errati. Trascorri anche meno tempo a scrivere codice per gestire le condizioni di errore e hai maggiori probabilità di scrivere in anticipo il codice di gestione degli errori.

In molti casi questi vincoli possono essere definiti in fase di compilazione, nel qual caso è possibile scrivere un filtro per assicurarsi che l'attributo rientri sempre nell'intervallo o il tentativo di salvare l'attributo non riesce.

Tuttavia, in molti casi questi vincoli possono cambiare in fase di esecuzione. Ad esempio, potresti avere una tabella "auto" che ha "colore" come attributo che inizialmente assume i valori, ad esempio, di "rosso", "verde" e "blu". Durante l'esecuzione del programma è possibile aggiungere colori validi all'elenco iniziale e le nuove "auto" aggiunte possono assumere qualsiasi colore nell'elenco aggiornato dei colori. Inoltre, di solito si desidera che questo elenco aggiornato di colori sopravviva al riavvio del programma.

Per rispondere alla tua domanda, risulta che se hai un requisito per il vincolo di dati che può cambiare in fase di esecuzione e tali modifiche devono sopravvivere al riavvio del programma, le chiavi esterne sono la soluzione più semplice e concisa al problema. Il costo di sviluppo è l'aggiunta di una tabella (ad esempio "colori", un vincolo di chiave esterna alla tabella "auto" e un indice) e il costo di runtime è la ricerca di tabella aggiuntiva per i colori aggiornati per convalidare i dati e questo costo di runtime è generalmente mitigato dall'indicizzazione e dalla memorizzazione nella cache.

Se non si utilizzano chiavi esterne per questi requisiti, è necessario scrivere software per gestire l'elenco, cercare voci valide, salvarlo su disco, strutturare i dati in modo efficiente se l'elenco è grande, assicurarsi che eventuali aggiornamenti all'elenco non funzionino corrompere il file dell'elenco, fornire accesso seriale all'elenco nel caso in cui vi siano più lettori e/o scrittori e così via. vale a dire è necessario implementare molte funzionalità RDBMS.

0
Jay Godse

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.

0
Kilhoffer

Q uite spesso riceviamo gli errori con vincoli FK Impossibile aggiungere o aggiornare una riga figlio: un vincolo di chiave esterna non riesce Supponiamo che ci siano due tabelle inventario_origine e contratto_line, e stiamo facendo riferimento inventario_origine_dell'inventario_line da inventario_origine e supponiamo di voler eliminare il record da inventario_origine e il record è già presente nelle righe_lavoro oppure vogliamo eliminare la colonna PK dalla tabella Base, otteniamo errori per i vincoli FK, possiamo evitarlo usando i passaggi indicati di seguito.

CREATE TABLE inventory_source (
inventory_source_id int(11) NOT NULL AUTO_INCREMENT,
display_name varchar(40) NOT NULL,
state_id int(11) NOT NULL,
PRIMARY KEY (inventory_source_id),
KEY state_id (state_id),
CONSTRAINT ba_inventory_source_state_fk FOREIGN KEY (state_id) REFERENCES   ba_state (state_id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE contract_lines(
contract_line_id int(11) NOT NULL AUTO_INCREMENT,
inventory_source_id int(11) NULL ,
PRIMARY KEY (contract_line_id),
UNIQUE KEY contract_line_id (contract_line_id),
KEY AI_contract_line_id (contract_line_id),
KEY contract_lines_inventory_source_fk (inventory_source_id),
CONSTRAINT contract_lines_inventory_source_fk FOREIGN KEY       (inventory_source_id) REFERENCES ba_inventory_source (inventory_source_id)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8 ;

Possiamo superarlo usando i seguenti passaggi: -

  1. L'eliminazione o l'aggiornamento della riga dall'inventario_sorgente eliminerà o aggiornerà automaticamente le righe corrispondenti nella tabella contract_lines e questo è noto come eliminazione o aggiornamento in cascata.
  2. Un altro modo per farlo è impostare la colonna cioè inventario_origine_id nella tabella contract_lines su NULL, quando un record corrispondente ad esso viene eliminato nella tabella inventario_origine.
  3. Possiamo limitare la tabella padre per l'eliminazione o l'aggiornamento, in altre parole si può rifiutare l'operazione di eliminazione o aggiornamento per la tabella inventario_origine.
  4. Il tentativo di eliminare o aggiornare un valore di chiave primaria non sarà autorizzato a procedere se nella tabella di riferimento è presente un valore di chiave esterna correlato.
0
Vikas Kukreti