Domanda

Ho queste tabelle:

Projects(projectID, CreatedByID)
Employees(empID,depID)
Departments(depID,OfficeID)
Offices(officeID)

CreatedByID è una chiave esterna per Employees. Ho una query che funziona per quasi ogni caricamento della pagina.

È una cattiva pratica aggiungere semplicemente una colonna OfficeID ridondante a Projects per eliminare i tre join? O dovrei fare quanto segue:

SELECT * 
FROM Projects P
JOIN Employees E   ON P.CreatedBY = E.EmpID
JOIN Departments D ON E.DepID = D.DepID
JOIN Offices O     ON D.officeID = O.officeID
WHERE O.officeID = @SomeOfficeID

Nella programmazione dell'applicazione I " Scrivere prima con le best practice e successivamente ottimizzare " ma gli amministratori del database avvisano sempre del costo dei join.

È stato utile?

Soluzione

La denormalizzazione ha il vantaggio di SELECT s veloci su query di grandi dimensioni.

Gli svantaggi sono:

  • Ci vuole più tempo e codice per garantire l'integrità (che è molto importante nel tuo caso)

  • È più lento su DML (INSERT / UPDATE / DELETE)

  • Ci vuole più spazio

Per quanto riguarda l'ottimizzazione, è possibile ottimizzare o per query più veloci o per DML più veloci (di norma, questi due sono antagonisti).

L'ottimizzazione per una query più veloce spesso implica la duplicazione di dati, che si tratti di denormalizzazione, indici, tabelle extra di qualunque cosa.

In caso di indici, RDBMS lo fa per te, ma in caso di denormalizzazione, dovrai codificarlo tu stesso. Cosa succede se Department si sposta su un altro Office? Dovrai risolverlo in tre tabelle anziché in una.

Quindi, come posso vedere dai nomi delle tue tabelle, non ci saranno milioni di record lì. Quindi è meglio normalizzare i tuoi dati, sarà più semplice da gestire.

Altri suggerimenti

Normalizza fino a quando non fa male, quindi denormalizza fino a quando funziona

Normalizza sempre per quanto necessario per rimuovere i problemi di integrità del database (ovvero potenziali dati duplicati o mancanti).

Anche se ci sono stati miglioramenti delle prestazioni dalla denormalizzazione (che di solito non è il caso), il prezzo della perdita di integrità dei dati è troppo alto per giustificare.

Basta chiedere a chiunque abbia dovuto lavorare per risolvere tutti i problemi oscuri di un database legacy se preferirebbero dati validi o aumenti insignificanti (se del caso).

Inoltre, come menzionato da John, se si finisce per aver bisogno di dati denormalizzati (per velocità / report / ecc.), crearli in una tabella separata, preservando i dati grezzi.

Il costo dei join non dovrebbe preoccuparti troppo di per sé (a meno che tu non stia cercando di ridimensionare a milioni di utenti, nel qual caso dovresti assolutamente preoccuparti).

Sarei più preoccupato per l'effetto sul codice che lo chiama. I database normalizzati sono molto più facili da programmare e portano quasi sempre a una migliore efficienza all'interno dell'applicazione stessa.

Detto questo, non normalizzarti oltre i limiti della ragione. Ho visto la normalizzazione per il bene della normalizzazione, che di solito finisce in un database che ha una o due tabelle di dati effettivi e 20 tabelle riempite con nient'altro che chiavi esterne. Questo è chiaramente eccessivo. La regola che utilizzo normalmente è: se i dati in una colonna sarebbero altrimenti duplicati, dovrebbero essere normalizzati.

I DBA dovrebbero essere preoccupati se il tuo db non è correttamente normalizzato all'inizio. Dopo aver misurato attentamente le prestazioni e determinato di avere colli di bottiglia, potresti iniziare a denormalizzare, ma sarei estremamente cauto.

Sarei più preoccupato per i DBA che ti avvertono del costo dei join, a meno che tu non sia in una situazione altamente patologica.

Non dovresti guardare alla denormalizzazione prima di aver provato tutto il resto.

Le prestazioni di questo sono davvero un problema? Il tuo database ha alcune funzionalità che puoi usare per velocizzare le cose senza compromettere l'integrità? Puoi migliorare le tue prestazioni memorizzando nella cache?

È meglio mantenere quello schema nella terza forma normale e lasciare che il tuo DBA si lamenti del costo dei join.

Se stai usando numeri interi (o BIGINT) come ID e sono la chiave primaria in cluster, dovresti andare bene.

Anche se sembra che sarebbe sempre più veloce trovare un ufficio da un progetto dato che stai sempre cercando le chiavi primarie, l'uso degli indici sulle chiavi esterne renderà la differenza minima poiché anche gli indici copriranno le chiavi primarie.

Se in seguito dovessi riscontrare la necessità di denormalizzare i dati, puoi creare una tabella cache in base a una pianificazione o a un trigger.

Normalizza per modellare i concetti nel tuo design e la loro relazione. Pensa a quali relazioni possono cambiare e cosa significherà un cambiamento del genere in termini di design.

Nello schema che hai pubblicato, c'è quello che mi sembra un errore evidente (che potrebbe non essere un errore se hai un caso speciale in termini di come funziona la tua organizzazione) - c'è un'ipotesi implicita che ogni dipartimento si trova esattamente in un ufficio e che tutti i dipendenti che si trovano nello stesso dipartimento lavorano in quell'ufficio.

Cosa succede se il dipartimento occupa due uffici?

Cosa succede se un dipendente appartiene nominalmente a un dipartimento, ma lavora fuori da un ufficio diverso (supponendo che ti riferisca a uffici fisici)?

Nell'esempio, gli indici impostati correttamente nelle tabelle dovrebbero consentire che i join si verifichino in modo estremamente rapido e si ridimensionino bene a 100.000 righe. Questo è di solito l'approccio che prendo per aggirare il problema.

Ci sono volte in cui i dati vengono scritti una volta e selezionati per il resto della sua vita in cui non ha davvero senso fare una dozzina di join ogni volta.

Non denormalizzare.

Progetta i tuoi tavoli secondo principi di progettazione semplici e solidi che faciliteranno l'implementazione del resto del tuo sistema. Facile da compilare, popolare, utilizzare e amministrare il database. Facile e veloce per eseguire query e aggiornamenti. Facile da modificare ed estendere il design del tavolo quando la situazione lo richiede e non necessario per ragioni leggere e transitorie.

Un insieme di principi di progettazione è la normalizzazione. La normalizzazione porta a tabelle facili e veloci da aggiornare (inclusi inserti ed eliminazioni). La normalizzazione elimina le anomalie di aggiornamento e elimina la possibilità di un database che si contraddice. Questo impedisce un sacco di bug rendendoli impossibili. Inoltre impedisce molti colli di bottiglia degli aggiornamenti rendendoli inutili. Questo va bene.

Esistono altri insiemi di principi di progettazione. Portano a progetti di tavoli che non sono completamente normalizzati. Ma questo non è & Quot; denormalizzazione & Quot ;. È solo un design diverso, un po 'incompatibile con la normalizzazione.

Un insieme di principi di progettazione che porta a un design radicalmente diverso dalla normalizzazione è il design dello schema a stella. Lo schema a stella è molto veloce per le query. Anche i join e le aggregazioni su larga scala possono essere eseguiti in un tempo ragionevole, dato un buon DBMS, una buona progettazione fisica e hardware sufficiente per svolgere il lavoro. Come prevedibile, uno schema a stella presenta anomalie di aggiornamento. È necessario programmare queste anomalie quando si tiene aggiornato il database. Avrai generalmente bisogno di un processo ETL strettamente controllato e attentamente costruito che aggiorni lo schema a stella da altre fonti di dati (forse normalizzate).

L'uso dei dati memorizzati in uno schema a stella è estremamente semplice. È così facile che usando una sorta di OLAP e un motore di report, puoi ottenere tutte le informazioni necessarie senza scrivere alcun codice e senza sacrificare troppo le prestazioni.

Ci vuole un'analisi dei dati buona e piuttosto approfondita per progettare un buon schema normalizzato. Errori e omissioni nell'analisi dei dati possono comportare dipendenze funzionali da scoprire. Questi FD da scoprire comporteranno involontarie deviazioni dalla normalizzazione.

Ci vuole anche un'analisi dei dati buona e piuttosto approfondita per progettare e costruire un buon schema a stella. Errori e commissioni nell'analisi dei dati possono comportare scelte sfavorevoli in termini di dimensioni e granularità. Ciò renderà quasi impossibile costruire ETL e / o rendere inadeguata la capacità di trasporto di informazioni della stella per le esigenze emergenti.

Un'analisi dei dati buona e piuttosto approfondita non dovrebbe essere una scusa per la paralisi dell'analisi. L'analisi deve essere corretta e ragionevolmente completa in breve tempo. Più breve per progetti più piccoli. La progettazione e l'implementazione dovrebbero essere in grado di sopravvivere ad alcune aggiunte e correzioni tardive all'analisi dei dati e ai requisiti, ma non a un flusso costante di revisioni dei requisiti.

Questa risposta si espande sulla tua domanda originale, ma penso che sia rilevante per il progettista di database.

Normalizzazione : è una decisione di qualità.

Denormalization : è una decisione di prestazione.

Ecco perché si dice -

  

Normalizza fino a quando non fa male, De-normalizza fino a quando funziona.


Le seguenti decisioni sulla qualità indicano quale è la forma meno normale con cui puoi convivere:

  1. Quanta non ridondanza è importante per i tuoi tavoli?
  2. Quanto veloce vuoi la gestione dei dati?
  3. Quanto chiaro vuoi la relazione tra le tue tabelle?

Le seguenti decisioni sulle prestazioni indicano qual è la massima forma normale accettabile per i tuoi clienti / clienti / applicazioni :

  1. La risposta del mio database è abbastanza veloce?
  2. Troppi join causano un rallentamento?

Dopo aver corretto la forma normale minima e massima accettabile nel tuo caso, scegli la forma normale ovunque tra.

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