Normalizzazione

La progettazione logica del database, incluse le tabelle e le relazioni tra tabelle, è di fondamentale importanza per ottenere un database relazionale ottimizzato. Se si esegue una progettazione logica corretta, si hanno buone probabilità di ottenere prestazioni ottimali dal database e dall'applicazione. Se si esegue una progettazione logica inadeguata, potrebbero verificarsi effetti negativi sulle prestazioni dell'intero sistema.

La normalizzazione della progettazione logica del database comporta l'utilizzo di metodi formali per la suddivisione dei dati in più tabelle correlate. La presenza di diverse tabelle di piccole dimensioni con un numero minore di colonne caratterizza i database normalizzati. Un numero minore di tabelle di grandi dimensioni con un numero maggiore di colonne è tipico di un database non normalizzato.

Di norma un livello ragionevole di normalizzazione comporta un miglioramento delle prestazioni. Quando sono disponibili indici utili, Query Optimizer di SQL Server seleziona in modo efficace join tra tabelle rapidi ed efficienti.

Di seguito vengono indicati alcuni vantaggi garantiti dalla normalizzazione:

  • Ordinamento e creazione dell'indice più veloci.

  • Indici cluster più numerosi. Per ulteriori informazioni, vedere Linee guida per la progettazione di indici cluster.

  • Indici più compatti e con un minor numero di colonne.

  • Numero minore di indici per tabella. Ciò migliora le prestazioni delle istruzioni INSERT, UPDATE e DELETE.

  • Un numero minore di valori Null e minor rischio di inconsistenze. Ciò aumenta la compattezza del database.

Aumentando il grado di normalizzazione, aumentano il numero e la complessità dei join necessari per recuperare i dati. Un numero troppo elevato di join relazionali complessi tra un numero troppo elevato di tabelle può rallentare le prestazioni. Una normalizzazione ragionevole è spesso caratterizzata da un numero basso di query eseguite regolarmente le quali utilizzano join che coinvolgono più di quattro tabelle.

A volte la progettazione logica del database è già stata eseguita e una riprogettazione totale non è realizzabile. Anche in questo caso, tuttavia, sarà possibile normalizzare selettivamente una tabella di grandi dimensioni in diverse tabelle più piccole. Se per accedere al database si utilizzano stored procedure, è possibile implementare questa modifica dello schema senza interessare le applicazioni. In caso contrario, è possibile creare una vista che nasconde la modifica dello schema alle applicazioni.

Ottenere un database progettato in modo efficiente

Nella teoria della progettazione di database relazionali, le regole di normalizzazione identificano alcuni attributi che devono essere presenti o assenti in un database ben progettato. Una discussione completa delle regole della normalizzazione esula dagli scopi di questo argomento. Tuttavia, vi sono alcune regole che consentono di ottenere un database ben progettato:

  • Includere un identificatore in ogni tabella.

    La regola fondamentale della teoria della progettazione di database prevede di includere in ogni tabella un identificatore di riga univoco, una colonna o un set di colonne utilizzato per distinguere ogni record dagli altri record della tabella. A ogni tabella è necessario associare una colonna di ID e non sarà possibile assegnare lo stesso ID a record diversi. Una o più colonne utilizzate come identificatore di riga univoco per una tabella rappresentano la chiave primaria della tabella. Nel database AdventureWorks2008R2 ogni tabella contiene una colonna Identity come colonna chiave primaria. VendorID, ad esempio, è la chiave primaria per la tabella Purchasing.Vendor.

  • In una tabella è opportuno archiviare soltanto i dati di un solo tipo di entità.

    Se si tenta di archiviare troppe informazioni in una tabella, la gestione efficiente e affidabile dei dati della tabella può essere ostacolata. Nel database di esempio AdventureWorks2008R2, le informazioni sugli ordini e sui clienti sono archiviate in tabelle distinte. È possibile avere in una stessa tabella colonne con informazioni sugli ordini e colonne con informazioni sui clienti, ma una progettazione di questo tipo può comportare vari problemi. Le informazioni sui clienti, nomi e indirizzi, devono essere aggiunte e archiviate in modo ridondante per ogni ordine di vendita e questo comporta l'utilizzo di spazio di archiviazione aggiuntivo nel database. Se l'indirizzo di un cliente cambia, la modifica deve essere apportata a tutti gli ordini di vendita. Se, inoltre, l'ultimo ordine di un cliente viene rimosso dalla tabella Sales.SalesOrderHeader, le informazioni su tale cliente vanno perse.

  • In una tabella non includere colonne che ammettono valori Null.

    Nelle tabelle è possibile definire colonne che supportano valori Null. Un valore Null indica che non è presente alcun valore. Sebbene in casi isolati il supporto dei valori Null sia utile, è opportuno limitarne l'impiego. Il motivo è che richiedono una gestione speciale, che rende più complesse le operazioni sui dati. Se è disponibile una tabella con più colonne che ammettono valori Null e in diverse righe delle colonne sono inclusi valori Null, è consigliabile inserire tali colonne in un'altra tabella collegata alla tabella primaria. Se si archiviano i dati in due tabelle distinte, la tabella primaria può essere semplice e al tempo stesso può gestire occasionalmente l'esigenza di archiviare informazioni di questo tipo.

  • In una tabella non includere colonne o valori ripetuti.

    La tabella di un elemento del database non deve includere l'elenco di valori relativi a un'informazione specifica. Ad esempio, un prodotto del database AdventureWorks2008R2 può venire acquistato da più fornitori. La presenza nella tabella Production.Product di una colonna per il nome del fornitore creerebbe un problema. Una soluzione consiste nell'archiviare nella colonna i nomi di tutti i fornitori. Questo, tuttavia, rende difficile visualizzare un elenco dei singoli fornitori. Un'altra soluzione consiste nel modificare la struttura della tabella per aggiungere un'altra colonna per il nome del secondo fornitore. Questa soluzione, tuttavia, consente di gestire solo due fornitori. Se un libro è stato scritto da tre autori, inoltre, sarà necessario aggiungere un'altra colonna.

    Se è necessario archiviare un elenco di valori in un'unica colonna o se sono disponibili più colonne per un unico dato, ad esempio TelephoneNumber1 e TelephoneNumber2, è consigliabile inserire i dati duplicati in un'altra tabella con un collegamento alla tabella primaria. Nel database AdventureWorks2008R2 sono disponibili una tabella Production.Product per le informazioni sui prodotti, una tabella Purchasing.Vendor per le tabelle sui fornitori e una terza tabella Purchasing.ProductVendor. Nella terza tabella sono archiviati solo gli ID dei prodotti e gli ID dei fornitori dei prodotti. Questa progettazione consente di gestire un numero qualsiasi di fornitori di un prodotto senza modificare la definizione delle tabelle e senza allocare spazio inutilizzato ai prodotti con un solo fornitore.