CodeGym /Corsi /SQL SELF /Esempi di denormalizzazione dei dati e le sue conseguenze...

Esempi di denormalizzazione dei dati e le sue conseguenze

SQL SELF
Livello 25 , Lezione 4
Disponibile

La normalizzazione risolve alcuni problemi, ma in certi casi ne crea altri, soprattutto quando si parla di performance. Oggi ti apriamo le porte all’arte oscura (e a volte luminosa) della denormalizzazione. Sì, puoi infrangere le regole della normalizzazione... ma solo con la testa sulle spalle!

La denormalizzazione è il processo opposto alla normalizzazione. Se la normalizzazione divide le tabelle in entità logiche separate per minimizzare la ridondanza, la denormalizzazione riunisce i dati per migliorare le performance. La denormalizzazione viene spesso usata quando, sotto carichi elevati e con query complesse frequenti, il join di molte tabelle inizia a rallentare il sistema.

Si può dire che la denormalizzazione è un compromesso tra la purezza dei dati e la velocità delle query.

Quando usare la denormalizzazione?

Come per ogni strumento, è importante sapere quando la denormalizzazione è adatta. Si applica nelle seguenti situazioni:

  1. Le query usate spesso diventano lente. Quando un sistema sotto carico esegue spesso le stesse query (tipo report aggregati e riepiloghi), i join di molte tabelle possono richiedere molto tempo. La denormalizzazione permette di ridurre il numero di questi join.

  2. Task analitici e statistiche. Nei sistemi analitici (tipo BI — Business Intelligence) spesso serve fare analisi di grandi volumi di dati. In questi casi la denormalizzazione accelera l’elaborazione grazie ai dati “preparati” in anticipo.

  3. Query complesse. Se per una query devi fare join tra cinque, dieci o anche più tabelle, questo può rallentare parecchio il database. La denormalizzazione permette di semplificare la struttura delle query.

  4. Il numero di join supera il buon senso. Se hai query con 25 tabelle in JOIN, forse è il momento di rivedere il tuo approccio.

Esempi di denormalizzazione

Esempio 1: E-commerce. In un database normalizzato di un e-commerce potresti avere queste tabelle:

  1. customers — dati sui clienti.
  2. orders — info sugli ordini.
  3. products — dati sui prodotti.
  4. order_items — prodotti inclusi nell’ordine.

Una query per ottenere le informazioni potrebbe essere tipo questa:

SELECT
    c.customer_name,
    o.order_date,
    p.product_name,
    oi.quantity
FROM 
    customers c
JOIN 
    orders o ON c.customer_id = o.customer_id
JOIN 
    order_items oi ON o.order_id = oi.order_id
JOIN 
    products p ON oi.product_id = p.product_id
WHERE 
    c.customer_id = 42;

Ma cosa succede se il nostro e-commerce gestisce centinaia di migliaia di ordini al giorno? Questa query diventa troppo lenta per via dei troppi join.

Soluzione: denormalizzazione.

Creiamo una tabella per le info usate spesso:

CREATE TABLE order_summary AS
SELECT 
    c.customer_id,
    c.customer_name,
    o.order_id,
    o.order_date,
    p.product_id,
    p.product_name,
    oi.quantity
FROM 
    customers c
JOIN 
    orders o ON c.customer_id = o.customer_id
JOIN 
    order_items oi ON o.order_id = oi.order_id
JOIN 
    products p ON oi.product_id = p.product_id;

Ora, quando ci servono i dati, basta fare una query su order_summary:

SELECT * FROM order_summary WHERE customer_id = 42;

Esempio 2: Sistema di analytics. Immagina di lavorare con un database per un’azienda che vende biglietti per eventi. Hai queste tabelle:

  1. events — info sugli eventi.
  2. sales — dati sulle vendite dei biglietti.

Se agli analisti serve un report sul ricavo medio per biglietto su tutti gli eventi, la struttura normalizzata ti costringe a fare una query aggregata ogni volta:

SELECT
    e.event_name,
    AVG(s.price) AS avg_ticket_price
FROM 
    events e
JOIN 
    sales s ON e.event_id = s.event_id
GROUP BY 
    e.event_name;

Questa query può essere piuttosto lenta, soprattutto se ogni vendita occupa milioni di righe.

Soluzione: denormalizzazione. Creiamo una tabella separata con i dati aggregati:

CREATE TABLE event_summary AS
SELECT 
    e.event_id,
    e.event_name,
    COUNT(s.sale_id) AS ticket_count,
    SUM(s.price) AS total_revenue,
    AVG(s.price) AS avg_ticket_price
FROM 
    events e
JOIN 
    sales s ON e.event_id = s.event_id
GROUP BY 
    e.event_id, e.event_name;

Ora i report saranno più veloci a livello aggregato:

SELECT
    event_name, 
    avg_ticket_price 
FROM 
    event_summary;

Conseguenze della denormalizzazione

La denormalizzazione può sicuramente velocizzare le query, ma non è una bacchetta magica che risolve tutto. Ecco con cosa potresti avere a che fare se scegli questa strada.

Primo: duplicazione dei dati. Quando le stesse informazioni sono in più posti, la dimensione del database cresce in fretta e diventa più difficile gestirlo.

Secondo: aggiornare i dati ora è più complicato. Immagina di avere i dati di un cliente nella tabella customers e anche una copia in order_summary. Se il cliente cambia nome o indirizzo, devi ricordarti di aggiornare entrambi i posti. Se ti dimentichi, hai un errore perché i dati non coincidono più.

Terzo: con tutta questa ridondanza è facile confondersi e fare errori. È come avere più versioni dello stesso documento — a volte non sai più qual è quella giusta.

E infine, mantenere e sviluppare un database così è più difficile. Dovrai scrivere trigger o script apposta per tenere tutte le copie dei dati sincronizzate. È lavoro extra per gli sviluppatori.

Insomma, la denormalizzazione è uno strumento da usare con intelligenza, conoscendo bene pro e contro.

1
Sondaggio/quiz
Normalizzazione dei dati, livello 25, lezione 4
Non disponibile
Normalizzazione dei dati
Normalizzazione dei dati
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION