Ci sono due aspetti della domanda, ognuno con preoccupazioni leggermente diverse.
Is a correctly normalized database the only consideration when attempting to deliver a data store with solid data integrity, and that is easily reported on?
No. L'integrità dei dati richiede anche constraints .
-
I vincoli della chiave primaria identificano univocamente un record. Ciò aiuta a prevenire i duplicati, ma non li impedisce necessariamente.
-
I vincoli delle chiavi esterne aiutano a garantire che i dati correlati siano mantenuti sincronizzati: una tabella per "numeri di telefono dei clienti" dovrebbe avere un "cliente" corrispondente, ad esempio. I record orfani e i dati mancanti danneggiano l'integrità dei dati.
-
I vincoli di campo / colonna possono aiutare a garantire che i dati siano validi. Ad esempio, forse un numero di telefono è memorizzato in un campo VARCHAR
ma non deve memorizzare lettere o formattazione, solo numeri . Un vincolo può garantire che se i dati esistono, soddisfa criteri arbitrari che lo rendono valido per lo schema dato.
If so, does more normalization tend to lead to more reportable data?
La normalizzazione tende a portare a dati meno riferibili. Il motivo è che un tipico schema RDBMS è progettato attorno a ORM, che significa "oggetti applicazione". Quello che sembra un oggetto può richiedere più tabelle:
-
Una classe che utilizza l'ereditarietà (ad esempio ha sottoclassi) richiede in pratica una tabella per livello di ereditarietà perché i membri dati secondari non sono applicabili alla superclasse e dovrebbero avere la propria tabella.
-
Gli oggetti correlati possono avere la propria tabella. Un cliente con più numeri di telefono potrebbe essere List<String>
nell'applicazione, ma i numeri di telefono potrebbero trovarsi nella propria tabella nello schema che forma una relazione 0..*
.
I rapporti spesso sono basati su record dove un record è specifico del rapporto. Spesso denormalizzano i dati per dare una vista di una tabella specifica con i dati correlati mescolati. Questo è normalmente in contrasto con la normalizzazione e l'ORM.
Ciò significa che un oggetto che si utilizza abbastanza facilmente nell'applicazione potrebbe esplodere in molte tabelle nello schema del database, aggiungendo relazioni con cardinalità variabile. Ciò richiede join quando si scrive una query di report, alcuni dei quali potrebbero essere complessi o richiedere subquery. Ho visto query SQL di report con dieci o più join, subquery correlate, aggregati e altre funzionalità intermedie e avanzate di SQL che aggiungono complessità e possono danneggiare le prestazioni delle query.
Il modo tipico per affrontare questo come ho visto professionalmente è avere un set separato di tabelle di reporting denormalizzate create per i tuoi report. Utilizzare i trigger o le stored procedure per popolarli. Questo è più lavoro durante la persistenza, ma consente di risparmiare un sacco di tempo e di tirare i capelli quando scrivi SQL per i tuoi rapporti.
Puoi anche usare il codice dell'applicazione: quando salvi un oggetto e lo hai in memoria e i suoi oggetti correlati, costruisci una query per inserire o aggiornare un record nelle tue tabelle di rapporto. Questo potrebbe essere più facile e avere prestazioni di runtime più veloci rispetto a fare affidamento sui trigger.