La cosa interessante di questo thread di domande e risposte è che in realtà ci sono 3 domande. Tutti hanno risposto a una diversa, e quasi nessuno ha risposto alla prima:
- Perché non sono alcuni database in natura normalizzate?
- Perché / quando un database normalizzato dovrebbe essere denormalizzato ?
- In quali situazioni è dannoso o non necessario in primo luogo normalizzare?
I lettori attenti noteranno che si tratta di domande molto diverse e cercherò di rispondere a ciascuna di esse separatamente evitando troppi dettagli. Con "troppo" intendo che non penso che questo sia il contesto appropriato in cui svolgere un ampio dibattito sul merito di vari argomenti a favore o contro la normalizzazione; Spiegherò semplicemente quali sono questi argomenti, magari elencherò alcune avvertenze e salverò la filosofia per domande più specifiche, se mai dovessero emergere.
Inoltre, in questa risposta presumo che la "normalizzazione" implichi "BCNF, 3NF o almeno 2NF" , poiché questo è il livello di normalizzazione che i progettisti generalmente mirano a raggiungere. È più raro vedere disegni 4NF o 5NF; sebbene non siano certamente obiettivi impossibili, si preoccupano della semantica delle relazioni piuttosto che della loro rappresentazione , che richiede una conoscenza considerevolmente maggiore sul dominio.
Quindi, verso l'alto e verso l'alto:
1. Perché alcuni database in the wild non sono normalizzati?
La risposta a questo potrebbe essere "perché non dovrebbero essere", ma fare quell'assunto fin dall'inizio è un lavoro investigativo piuttosto scadente. Non faremmo grandi progressi come società se operassimo sempre sul presupposto che qualunque cosa sia, dovrebbe essere.
Le vere ragioni per cui i database non vengono normalizzati in primo luogo sono più complicate. Ecco i primi 5 che ho incontrato:
Gli sviluppatori che l'hanno progettato non sapevano o non capivano come normalizzare. La prova evidente di ciò si presenta sotto forma di molte altre scelte di progettazione di accompagnamento, come l' uso di colonne varchar per tutto o avere un pasticcio di spaghetti con nomi di tabelle e colonne insignificanti . E ti assicuro che ho visto database "reali" che sono altrettanto dannosi di quelli degli articoli TDWTF.
Agli sviluppatori che lo hanno progettato non importava o erano attivamente contrari alla normalizzazione in linea di principio . Nota, qui non sto parlando di casi in cui è stata presa una decisione deliberata di non normalizzare sulla base di analisi contestuali, ma piuttosto team o aziende in cui la normalizzazione è più o meno compresa ma semplicemente ignorata o evitata per abitudine. Ancora una volta, sorprendentemente comune.
Il software è / è stato fatto come un progetto Brownfield . Molti puristi ignorano questo business perfettamente legittimo piuttosto che una ragione tecnica per non normalizzare. A volte in realtà non riesci a progettare un nuovo database da zero, devi agganciarti a uno schema legacy esistente e tentare di normalizzare a quel punto comporterebbe troppo dolore. 3NF non fu inventato fino al 1971 e alcuni sistemi - in particolare i sistemi finanziari / contabili - hanno le loro radici ancora più indietro di così!
Il database era originariamente normalizzato , ma un accumulo di piccole modifiche per un lungo periodo di tempo e / o un team ampiamente distribuito hanno introdotto sottili forme di duplicazione e altre violazioni di qualunque forma normale fosse originariamente in atto. In altre parole, la perdita di normalizzazione è stata accidentale e troppo poco tempo è stato dedicato al refactoring.
È stata presa una deliberata decisione aziendale di non dedicare alcun tempo all'analisi aziendale o alla progettazione di database e semplicemente "farlo". Questa è spesso una falsa economia e alla fine diventa una forma crescente di debito tecnico , ma a volte è una decisione razionale, almeno basata su informazioni che erano conosciute all'epoca - ad esempio, il database potrebbe essere stato inteso come un prototipo ma è finito essere promosso all'uso della produzione a causa di vincoli di tempo o cambiamenti nell'ambiente aziendale.
2. Perché / quando un database normalizzato dovrebbe essere denormalizzato?
Questa discussione si presenta spesso quando un database è normalizzato per cominciare. O le prestazioni sono scadenti o c'è molta duplicazione nelle query (join) e il team ritiene, giustamente o erroneamente, di aver fatto tutto il possibile con il progetto attuale. È importante notare che la normalizzazione migliora le prestazioni per la maggior parte del tempo e ci sono diverse opzioni per eliminare i join in eccesso quando la normalizzazione sembra funzionare contro di te, molti dei quali sono meno invasivi e rischiosi rispetto al semplice passaggio a un modello denormalizzato:
Crea viste indicizzate che incapsulano le aree problematiche più comuni. I DBMS moderni sono in grado di renderli inseribili o aggiornabili (ad esempio INSTEAD OF
trigger di SQL Server ). Questo ha un leggero costo per le dichiarazioni DML sulle tabelle / indici sottostanti, ma è generalmente la prima opzione che dovresti provare perché è quasi impossibile sbagliare e non costa quasi nulla da mantenere. Naturalmente, non tutte le query possono essere trasformate in una vista indicizzata: le query aggregate sono le più problematiche. Il che ci porta al prossimo articolo ...
Creare tabelle aggregate denormalizzate che vengono automaticamente aggiornate dai trigger. Queste tabelle esistono in aggiunta alle tabelle normalizzate e formano una sorta di modello CQRS . Un altro modello CQRS, più popolare in questi giorni, è quello di utilizzare pub / sub per aggiornare i modelli di query, il che offre il vantaggio dell'asincronia, sebbene ciò non sia adatto in casi molto rari in cui i dati non possono essere obsoleti.
A volte, le visualizzazioni indicizzate non sono possibili, le velocità di transazione e i volumi di dati sono troppo elevati per ammettere trigger con prestazioni accettabili e le query devono sempre restituire dati in tempo reale. Queste situazioni sono rare - immagino che potrebbero applicarsi a cose come il trading ad alta frequenza o database di forze dell'ordine / intelligence - ma possono esistere. In questi casi non hai davvero altra scelta che denormalizzare le tabelle originali.
3. In quali situazioni è dannoso o non necessario in primo luogo normalizzare?
Ci sono, infatti, diversi buoni esempi qui:
Se il database viene utilizzato solo per report / analisi. In genere questo implica che esiste un database aggiuntivo e normalizzato utilizzato per OLTP, che viene periodicamente sincronizzato con il database di analisi tramite ETL o messaggistica.
Quando si applica un modello normalizzato richiederebbe un'analisi inutilmente complessa dei dati in arrivo. Un esempio di ciò potrebbe essere un sistema che deve memorizzare i numeri di telefono raccolti da diversi sistemi o database esterni. Si potrebbe denormalizzare il codice di chiamata e la zona, ma che avrebbe dovuto conto per tutti i diversi formati possibili, i numeri di telefono non validi, numeri di vanità (1-800-GET-STUFF), per non parlare di diversi locali. Di solito è più un problema di quanto non valga la pena, e i numeri di telefono vengono solitamente inseriti in un singolo campo a meno che tu non abbia una specifica esigenza aziendale per il prefisso.
Quando il database relazionale è principalmente lì per fornire supporto transazionale per un database aggiuntivo, non relazionale. Ad esempio, è possibile che si stia utilizzando il database relazionale come coda di messaggi o per tenere traccia dello stato di una transazione o di una saga, quando i dati primari vengono archiviati in Redis o MongoDB o altro. In altre parole, i dati sono "dati di controllo". Di solito non ha senso normalizzare i dati che in realtà non sono dati aziendali .
Architetture orientate ai servizi che condividono un database fisico. Questo è un po 'di uno strano, ma in una vera e propria SOA, si avrà di tanto in tanto bisogno di avere dati duplicati fisicamente perché i servizi non sono autorizzati a query di dati direttamente l'un l'altro. Se si trovano a condividere lo stesso database fisico, i dati sembreranno non essere normalizzati, ma in generale, i dati di proprietà di ogni singolo servizio sono ancora normalizzati a meno che non sia presente uno degli altri fattori attenuanti. Ad esempio, un servizio di fatturazione potrebbe essere proprietario dell'entità fattura, ma il servizio di contabilità deve ricevere e archiviare la data e l'importo della fattura per includerla nelle entrate di quell'anno.
Sono sicuro che ci sono più ragioni che non ho elencato; quello a cui sto arrivando, in sostanza, è che sono abbastanza specifici e saranno abbastanza ovvi quando verranno in pratica. Database OLAP sono supposti a schemi utilizzo stelle, SOA sono suppone di avere alcuni doppioni, ecc Se si sta lavorando con un modello di architettura noto che semplicemente non funziona con la normalizzazione, allora non normalizzare; in generale, il modello di architettura ha la precedenza sul modello di dati.
E per rispondere all'ultima domanda:
È vero che buoni architetti ed esperti scelgono un design denormalizzato mentre gli sviluppatori non esperti scelgono il contrario? Quali sono gli argomenti contro l'avvio del tuo progetto con in mente la normalizzazione?
No, questo è completo e completo. BS È anche BS che gli esperti scelgono sempre un design normalizzato . Gli esperti non seguono solo un mantra. Ricercano, analizzano, discutono, chiariscono e ripetono, e quindi scelgono qualsiasi approccio abbia più senso per la loro situazione particolare.
Il database 3NF o BCNF è di solito un buon punto di partenza per l'analisi perché è stato provato e dimostrato con successo in decine di migliaia di progetti in tutto il mondo, ma poi di nuovo, così ha C. Ciò non significa che utilizziamo automaticamente C in ogni nuovo progetto. Le situazioni del mondo reale potrebbero richiedere alcune modifiche al modello o l'uso di un modello completamente diverso. Non lo sai finché non ti trovi in quella situazione.