[DB] Perché denormalizzare una basedati?

Prima di parlare della denormalizzazione di una basedati, ricordiamo cos’è la sua normalizzazione: è il procedimento che ha come conseguenza la riduzione della ridondanza all’interno del database, e che quindi consente un risparmio in termini di spazio occupato. Tale operazione andrebbe eseguita in fase di progettazione, riuscendo quindi subito ad identificare i dati raggruppabili in tabelle separate da mettere in relazione. Effettuare subito questo procedimento porta anche ad una migliore comprensione del database e dei legami che intercorrono tra le varie tabelle.

Ci sono tre diverse forme di normalizzazione (dette forme normali di Boyce e Codd):

  • la 1° Forma Normale (1NF) consiste nel fare in modo di non presentare gruppi di attributi che si ripetono (ossia ciascun attributo è definito su un dominio con valori atomici) e nel far esistere una chiave primaria per ciascuna relazione (ossia esiste un insieme di attributi, che identifica in modo univoco ogni tupla della relazione)
  • una volta portato il database alla 1° Forma Normale, dobbiamo portarlo alla 2° Forma Normale (2NF), ossia per ogni relazione tutti i campi non chiave dipendono funzionalmente dall’intera chiave composta e non da una parte di essa.
  • la 3° Forma Normale (3NF) si ha quando la relazione è, innanzitutto, in 2° forma normale e tutti gli attributi non-chiave dipendono dalla chiave soltanto, ossia non esistono attributi che dipendono da altri attributi non-chiave.

Per definizione, una relazione R è in forma normale di Boyce e Codd (BCNF) se e solo se è in 3NF e, per ogni dipendenza funzionale non banale X –> Y,  dove X è una superchiave per R.

In questo modo si riducono ulteriormente sia la ridondanza dei dati nelle tabelle che la possibilità di errori umani in fase di inserimento dei dati.

La denormalizzazione, invece, è il processo che permette di ottimizzare le performance in lettura di un database aggiungendo ridondanza nei dati o raggruppandoli. Tale operazione viene effettuata spesso per risolvere l’inefficienza dei database relazionali, visto che, se normalizzati, possono soffrire di pesantezza nel caricamento dei dati.

Quando si valuta la normalizzazione tra le alternative di progettazione di una basedati, è utile tenere presente le diverse tecniche che consentono di denormalizzare intenzionalmente un database. La denormalizzazione intenzionale dei dati può essere motivata dal rilevamento di problemi di prestazioni oppure nel caso in cui si desideri semplificare la creazione di report ad-hoc. I problemi di prestazioni derivano dalle query per le quali, in produzione, è richiesto un numero troppo elevato di join di tabelle con un accesso intensivo al disco. Lo scopo della creazione di report ad-hoc è consentire anche agli utenti finali di eseguire query non strutturate, in quanto è possibile che utenti finali poco esperti non siano certi delle procedure necessarie per ottenere informazioni da più tabelle correlate.

Le tecniche di denormalizzazione comprendono la duplicazione dei dati, la possibilità di disporre di dati di riepilogo, la suddivisoine di tabelle in partizioni orizzontali o verticali e la creazione di visualizzazioni denormalizzate per semplificare la creazione di report, ovvero un’alternativa intelligente che lascia invariato il database normalizzato.

Generalmente la denormalizzazione si usa trasformando le relazioni gerarchiche del tipo uno-a-molti in un’unica relazione e quindi in un’unica tabella. Come esempio di denormalizzazione, si consideri il caso degli indirizzi dei clienti. Di solito, una tabella dei clienti comprende gli attributi nome, via, città, stato e codice di avviamento postale. Anche se la città e lo stato possono essere ricavati direttamente dal codice di avviamento postale, per cui è possibile normalizzare la tabella dei clienti eliminando la città e lo stato dai dati di ogni cliente, è pratica comune lasciare l’indirizzo denormalizzato.

Gli indirizzi vengono denormalizzati per diversi motivi:

  • gli indirizzi vengono utilizzati in più posizioni (query, report, buste, schermate per il supporto ai clienti) e la denormalizzazione evita di aggiungere altro codice per la ricostruzione dell’indirizzo in tutta l’applicazione.
  • per le query basate sugli indirizzi viene utilizzata una sintassi SQL molto più semplice
  • gli errori di indirizzo sono limitati a singoli clienti.

Inoltre, una progettazione normalizzata permette di memorizzare differenti, ma relazionati, “pezzi” di informazione in tabelle separate logicamente (relazioni appunto). Se queste relazioni vengono fisicamente memorizzate su file system separati, il completamento di una query che recuperi le informazioni tra le diverse relazioni (con una operazione di join) potrebbe essere lento. Si preferisce, come metodo di ottimizzazione, memorizzare le informazioni in maniera ridondante e si affida al DBMS la responsabilità di mantenere consistenti queste copie ridondanti, come fanno Microsoft SQL Server (con le indexed views) o Oracle DB (con le materialized views), ma i dati vengono memorizzati sullo stesso file system.

La strategia che si preferisce è quella della denormalizzazione nella progettazione logica dei dati. La responsabilità della consistenza dei dati è affidata al progettista della basedati che crea delle regole (dette constraints) in modo da specificare come le copie ridondanti dell’informazione devono essere mantenute sincronizzate. Si accresce la complessità logica nella progettazione della base dati, dovuta all’inserimento di questi vincoli, ma si migliora notevolmente il tempo di accesso in lettura al database (SELECT in SQL), anche se si riducono le performance per le operazioni di scrittura (INSERT, UPDATE, DELETE) rispetto a quelle di scrittura sui db relazionali. Si accetta, dunque, una perdita della terza forma normale (anche della seconda volendo), aumentando la complessità della basedati, ma migliorando le performance in lettura.

La denormalizzazione è molto usata specie in contesti come il datawarehouse. In quel contesto, dove la velocità di risposta della banca dati a una query ha un’importanza maggiore rispetto all’organizzazione dei dati, è utile avere una denormalizzazione delle tabelle per evitare di fare delle join aggiuntive.

Questo aspetto di progettazione viene adottato in contesti big-data, dovendo migliorare le performance nella lettura di grosse quantità di dati, e lo stesso movimento NO-SQL lo rispetta nelll’implementazione di DB non relazionali (come MongoDB, REDIS, CouchDBJackrabbit, Cassandra, …)

Creative Commons License
This work by Francesco Ficetola is licensed under a Creative Commons Attribution 4.0 International License.
Based on a work at www.francescoficetola.it.
Permissions beyond the scope of this license may be available at http://www.francescoficetola.it/2012/06/07/db-perche-denormalizzare-una-basedati/.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *


nove + = 16