Domanda

Trovo che questo si avvicina molto, e non sono sicuro il modo migliore per avvicinarsi.

La domanda che ho è come prendere la decisione tra l'utilizzo di chiavi esterne di ricercare le tabelle, o utilizzando i valori di tabella di ricerca direttamente nelle tabelle che ne facciano richiesta, evitando completamente il rapporto tabella di ricerca.

Punti da tenere a mente:

  • Con il secondo metodo si farebbe bisogno di fare gli aggiornamenti di massa a tutti record fanno riferimento i dati se viene modificato nella tabella di ricerca.

  • Questa è focalizzata più verso tabelle che hanno un sacco di riferimento molti ricerca della colonna un sacco di stranieri tables.Therefore chiavi significa un sacco di si unisce ogni volta che si esegue una query la tavolo.

  • Questi dati sarebbe venuta da goccia liste down se essere tirato dalle tabelle di ricerca. Al fine di abbinare i dati quando il ricaricamento, i valori devono essere nella lista esistente ( relativo al primo punto ).

C'è una buona pratica qui, o qualsiasi punti chiave da prendere in considerazione?

È stato utile?

Soluzione

È possibile utilizzare una tabella di ricerca con una chiave primaria VARCHAR, e la vostra tabella di dati principale utilizza una chiave esterna sulla sua colonna, con aggiornamenti a cascata.

CREATE TABLE ColorLookup (
  color VARCHAR(20) PRIMARY KEY
);

CREATE TABLE ItemsWithColors (
  ...other columns...,
  color VARCHAR(20),
  FOREIGN KEY (color) REFERENCES ColorLookup(color)
    ON UPDATE CASCADE ON DELETE SET NULL
);

Questa soluzione presenta i seguenti vantaggi:

  • È possibile interrogare i nomi dei colori nella tabella di dati principali senza richiedere un join alla tabella di ricerca.
  • Tuttavia, i nomi dei colori sono vincolati al set di colori nella tabella di ricerca.
  • È possibile ottenere un elenco di nomi di colori unici (anche se nessuno è attualmente in uso nei dati principale) interrogando la tabella di ricerca.
  • Se si cambia un colore nella tabella di ricerca, il cambio automatico a cascata a tutte le righe che fanno riferimento nella tabella dati principale.

E 'sorprendente per me che tante altre persone su questa discussione sembrano avere idee sbagliate su ciò che "normalizzazione" è. Utilizzando un chiavi surrogate (l ' "id" onnipresente) non ha nulla a che fare con la normalizzazione!


Re commento da @MacGruber:

Sì, la dimensione è un fattore. In InnoDB per esempio, ogni indice secondario memorizza il valore della chiave primaria della riga (s) in cui si verifica un dato valore di indice. Quindi, gli indici più secondari si hanno, maggiore è l'overhead per l'utilizzo di un tipo di dati "ingombrante" per la chiave primaria.

Anche questo influisce chiavi esterne; la colonna chiave esterna deve essere lo stesso tipo di dati come chiave primaria fa riferimento. Si potrebbe avere una piccola tabella di ricerca in modo da pensate che la dimensione della chiave primaria in una tabella di 50 righe non importa. Ma quella tabella di ricerca potrebbe essere referenziato da milioni o miliardi di righe in altre tabelle!

Non c'è una risposta giusta per tutti i casi. Qualsiasi risposta può essere corretta per diversi casi. Basta conoscere i compromessi, e cercare di prendere una decisione informata su un caso per caso.

Altri suggerimenti

In caso di semplici valori atomici, tendo a non essere d'accordo con l'opinione comune su questo, soprattutto sul fronte della complessità. Si consideri una tabella contenente i cappelli. Si può fare il modo "denormalizzato":

CREATE TABLE Hat (
  hat_id INT NOT NULL PRIMARY KEY,
  brand VARCHAR(255) NOT NULL,
  size INT NOT NULL,
  color VARCHAR(30) NOT NULL /* color is a string, like "Red", "Blue" */
)

Oppure si può normalizzare i più facendo una tabella di "colore":

CREATE TABLE Color (
  color_id INT NOT NULL PRIMARY KEY,
  color_name VARCHAR(30) NOT NULL
)

CREATE TABLE Hat (
  hat_id INT NOT NULL PRIMARY KEY,
  brand VARCHAR(255) NOT NULL,
  size INT NOT NULL,
  color_id INT NOT NULL REFERENCES Color(color_id)
)

Il risultato finale di questi ultimi è che avete aggiunto una certa complessità - invece di:

SELECT * FROM Hat

Ora avete da dire:

SELECT * FROM Hat H INNER JOIN Color C ON H.color_id = C.color_id

È che in più si uniscono un affare enorme? No - infatti, che è il fondamento del modello di design relazionale - normalizzazione consente di evitare possibili incoerenze nei dati. Ma ogni situazione come questa si aggiunge un po ' di complessità, e se non c'è una buona ragione, vale la pena chiedere il motivo per cui si sta facendo. Considero possibili "buone ragioni" per includere:

  • Ci sono altri attributi che "appendere off di" questo attributo? l'acquisizione, per esempio, sia "il nome del colore" e "valore esadecimale", in modo tale che il valore esadecimale dipende sempre il nome del colore ? Se è così, allora si vuole sicuramente una tabella di colori separati, per evitare situazioni in cui una fila ha ( "Rosso", "# FF0000") e un altro ha ( "Rosso", "# FF3333"). Più attributi correlati sono il segnale # 1 che un'entità dovrebbe essere normalizzata.
  • Sarà l'insieme dei possibili valori di cambiare spesso? Utilizzo di una tabella di ricerca normalizzato renderà le future modifiche agli elementi del set più facile, perché si sta solo aggiornando una singola riga. Se è raro, però, non esitano a dichiarazioni che devono aggiornare un sacco di righe della tabella principale invece; basi di dati sono abbastanza bravo in questo. Fare alcuni test di velocità, se non siete sicuri.
  • Sarà l'insieme dei possibili valori essere somministrata direttamente dagli utenti? Vale a dire c'è uno schermo dove si possono aggiungere / rimuovere / riordinare gli elementi della lista? Se è così, una tabella separata è un must, ovviamente.
  • l'elenco dei distinti potere valori qualche elemento dell'interfaccia utente? Ad es è "colore" un droplist nell'interfaccia utente? Allora sarete meglio averlo nella propria tabella, piuttosto che fare un SELECT DISTINCT sul tavolo ogni volta che è necessario mostrare la droplist.

Se nessuna di queste si applicano, sarei fatica a trovare un altro (buona) ragione per normalizzare. Se si desidera solo per fare in modo che il valore è uno di un certo (piccolo) insieme di valori di legge, è meglio utilizzare un vincolo che dice che il valore deve essere in un elenco specifico; mantiene le cose semplici, e si può sempre "upgrade" ad una tabella separata in seguito in caso di necessità.

Una cosa che nessuno ha considerato è che non si dovrebbe aderire alla tabella di ricerca se i dati in essa contenuti possono cambiare nel tempo e le registrazioni sono unito alla storica. L'esempio è una tabella parti e una tabella ordine. I venditori possono cadere parti o modificare i numeri di parte, ma la tabella ordini dovrebbero alawys avere esattamente ciò che è stato ordinato nel momento in cui è stato ordinato. Pertanto, dovrebbe occhiata i dati per fare l'inserto record, ma non deve mai unirsi alla tabella di ricerca per ottenere informazioni su un ordine esistente. Invece il numero di parte e la descrizione e il prezzo, ecc dovrebbero essere memorizzati nella tabella degli ordini. Questo è espceially critica in modo che le variazioni di prezzo non si propagano attraverso i dati storici e rendere il vostro record finanziari imprecisa. In questo caso, si potrebbe anche voler evitare l'uso di qualsiasi tipo di cascata aggiornamento pure.

scritto :

  

Il modo in cui abbiamo deciso di risolvere questo problema è con forma normale 4 °.   ...

Non è forma normale 4 °. Questo è un errore comune chiamato One True Lookup: http://www.dbazine.com/ofinterest/oi-articles/celko22

forma normale 4 ° è: http://en.wikipedia.org/wiki/Fourth_normal_form

La normalizzazione è abbastanza universalmente considerato come parte delle migliori pratiche nei database, e la normalizzazione dice sì, si spingono i dati fuori e si riferiscono ad esso con il tasto.

Si può anche fare una regola per il programma sempre contro i punti di vista, avendo la vista ottenere le ricerche.

In questo modo è possibile ottimizzare la vista e rendere il codice resistente ai cambiamenti nelle tabelle.

In Oracle, si potrebbe anche trasformare la vista in una vista materializzata, se mai hai bisogno di.

Dal momento che nessun altro ha affrontato il secondo punto:. Quando le query diventano lunghi e difficili da leggere e scrivere grazie a tutti coloro che si unisce, una vista di solito risolvere che

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