La progettazione logica riceve dal capitolo 10 i suoi input — schema concettuale, carico di lavoro, volume dati, vincoli di sistema — e produce lo schema logico del data mart. È qui che gli schemi di fatto del DFM si traducono in qualcosa di eseguibile: prima la scelta del modello logico (MOLAP, ROLAP o HOLAP), poi la scelta dello schema relazionale (stella o snowflake) e la traduzione di ogni costrutto del DFM — compresi quelli avanzati del capitolo 8, che ora rivelano il loro vero costo. Chiude il capitolo la stima dell'occupazione di memoria, il calcolo che il volume dati del capitolo 10 rende possibile e che negli esercizi d'esame accompagna ogni soluzione di progetto logico.
La modellazione concettuale è indipendente dal modello logico prescelto per l'implementazione; lo stesso non si può dire per la modellazione logica, che dipende da come il modello multidimensionale viene rappresentato fisicamente. Le slide distinguono due modelli logici di base:
I sistemi MOLAP (Multidimensional On-Line Analytical Processing) memorizzano i dati utilizzando strutture intrinsecamente multidimensionali (per esempio vettori multidimensionali). I sistemi ROLAP (Relational On-Line Analytical Processing) utilizzano il ben noto modello relazionale per la rappresentazione dei dati multidimensionali.
I vantaggi e i limiti del MOLAP sono speculari:
I sistemi commerciali si differenziano in base al modello logico adottato. Sebbene la maggior parte dei sistemi, soprattutto di grandi dimensioni, sia realizzata con soluzioni ROLAP, cominciano a essere proposte anche soluzioni ibride HOLAP (Hybrid-OLAP), che sfruttano le proprietà di entrambi i modelli.
Strutture multidimensionali native. Ottime prestazioni perché le operazioni non vanno simulate in SQL; soffre della sparsità (solo ~20% delle celle informative), della mancanza di strutture dati standard (strutture proprietarie) e della resistenza di progettisti e sistemisti abituati ai sistemi relazionali.
Modello relazionale. La modellazione multidimensionale si basa sullo schema a stella e sulle sue varianti. È la soluzione della maggior parte dei sistemi, soprattutto di grandi dimensioni; sfrutta la ventennale esperienza relazionale di progettisti e sistemisti.
Ibrido. Il DW ROLAP memorizza enormi quantità di dati; i DM MOLAP massimizzano la velocità di accesso; i cubi MOLAP possono anche essere creati «al volo» per specifiche sessioni di analisi what-if (report semi-statici).
Il problema della sparsità — solo una cella su cinque contiene informazioni — si affronta con due tecniche complementari:
La modellazione multidimensionale su sistemi relazionali è basata sullo schema a stella (star schema) e sulle sue varianti.
Uno schema a stella è composto da:
Le chiavi surrogate meritano una nota: sono chiavi generate dal sistema, prive di significato applicativo, che sostituiscono gli identificatori delle sorgenti. Il loro vantaggio è duplice: isolano la fact table dai cambiamenti delle chiavi naturali nelle sorgenti, e rendono la dimensione compatta (4 byte contro i molti byte di un codice applicativo). Nel calcolo dell'occupazione di memoria della sezione 16, il surrogato è sempre conteggiato a 4 byte.
Le slide aggiungono due considerazioni di fondo sullo schema a stella, una a favore e una contro:
Le dimension table sono completamente denormalizzate (per esempio Prodotto → Tipo): è sufficiente un join per recuperare tutti i dati relativi a una dimensione.
La denormalizzazione comporta una forte ridondanza nei dati: l'attributo «categoria» compare in ogni riga della dimension table Prodotto, replicato per ogni prodotto della stessa categoria.
C'è poi un vantaggio che riguarda la sparsità: non si hanno problemi di sparsità in uno schema a stella, poiché vengono memorizzate soltanto le tuple corrispondenti a punti dello spazio multidimensionale per cui esistono eventi. Il problema che affligge i cubi MOLAP (celle vuote che consumano spazio) semplicemente non si pone: se un evento non c'è, la tupla non esiste.
Un'interrogazione OLAP su uno schema a stella ha sempre la stessa forma: un group-by set di attributi dimensionali, una o più misure aggregate, e un numero di join pari alle dimensioni coinvolte. L'esempio delle slide chiede il totale della quantità venduta per i diversi tipi di prodotto, in ogni settimana e città, ma solo per i prodotti alimentari:
Notate la struttura: la fact table Vendite viene unita alle tre dimension table richieste dal group-by set (Settimane per la settimana, Negozi per la città, Prodotti per il tipo); la selezione opera su un attributo di una dimension table (Categoria), non sulla fact table. È lo schema di interrogazione che ritroverete in ogni esercizio — e la base di confronto per lo snowflake della prossima sezione.
Lo snowflake schema (schema a fiocco di neve) riduce la denormalizzazione delle dimension table degli schemi a stella, eliminando alcune delle dipendenze transitive che le caratterizzano.
Le dimension table DTᵢ,ⱼ di questo schema sono caratterizzate da: una chiave primaria (tipicamente surrogata) dᵢ,ⱼ; il sottoinsieme degli attributi di DTᵢ che dipendono funzionalmente da dᵢ,ⱼ; zero o più chiavi esterne importate da altre DTᵢ,ₖ, necessarie a garantire la ricostruibilità del contenuto informativo di DTᵢ. Sono primarie le dimension table le cui chiavi sono importate nella fact table; secondarie le rimanenti.
Le considerazioni delle slide sullo snowflake sono quattro:
La normalizzazione richiede particolare attenzione affinché nella nuova relazione sia spostato il corretto insieme di attributi. Le specifiche caratteristiche degli schemi a stella — in particolare la presenza di più dipendenze funzionali transitive in cascata — fanno sì che, affinché la decomposizione sia efficace, tutti gli attributi che dipendono (transitivamente e non) dall'attributo che ha determinato lo snowflaking siano posti nella nuova relazione.
Confrontate con la query sulla stella della sezione 5: la selezione su Categoria ora richiede due join in più (Prodotti → Tipi e Negozi → Città). È il prezzo, in tempo di esecuzione, dello spazio risparmiato dalla normalizzazione.
Esistono pareri contrastanti sull'utilità dello snowflaking: da un lato «contrasta con la filosofia del data warehousing» e rappresenta «un inutile abbellimento dello schema»; dall'altro, in quattro casi, può essere utile:
Il caso 1 è quello che si presta al calcolo: dato il frammento di gerarchia con le cardinalità (per esempio a (50.000), b (30.000), c (20.000), d (10.000), e (500), f (5.000), g (100), h (200), i (1.000)) e la lunghezza degli attributi (50 byte), dovete determinare il punto di snowflaking più vantaggioso dal punto di vista dello spazio. La regola operativa: confrontate l'occupazione con la gerarchia interamente nella dimension table primaria contro l'occupazione con lo snowflake applicato su ciascun attributo candidato — il punto di minimo è la risposta. Lo faremo numericamente nella sezione 16.
La regola di base per la traduzione di uno schema di fatto in uno schema a stella prevede di: creare una fact table contenente tutte le misure e gli attributi descrittivi direttamente collegati con il fatto e, per ogni gerarchia, creare una dimension table che ne contiene tutti gli attributi.
In aggiunta a questa semplice regola, la corretta traduzione di uno schema di fatto richiede una trattazione approfondita dei costrutti avanzati del DFM — esattamente quelli del capitolo 8. Le prossime sezioni li passano in rassegna uno per uno, con la loro traduzione logica.
| Costrutto DFM (cap. 8) | Traduzione logica | Sezione |
|---|---|---|
| Attributi descrittivi | Nella dimension table dell'attributo o nella fact table | 10 |
| Archi opzionali | Valori fittizi (NULL / NON APPLICABILE); tupla fittizia per l'opzionalità di gerarchia | 10 |
| Gerarchie condivise | Doppia importazione della chiave, oppure snowflake sul primo attributo condiviso | 11 |
| Convergenze | Attributi nella stessa dimension table dei padri | 11 |
| Attributi cross-dimensionali | Nuova tabella con chiave a₁…aₘ | 11 |
| Archi multipli | Bridge table (con peso) oppure push-down nella fact table | 12 |
| Dimensioni degeneri | Attributi importati direttamente nella fact table | 13 |
| Junk dimension | Unica dimension table per più dimensioni degeneri | 13 |
| Gerarchie incomplete | Valori fittizi (bilanciamento per esclusione / verso il basso / verso l'alto) | 14 |
| Gerarchie ricorsive | Autoanello oppure tabella di navigazione | 15 |
Questa tabella è la mappa del capitolo: ogni riga corrisponde a una sezione, e ogni sezione corrisponde a un quesito d'esame ricorrente («come si traduce a livello logico …?»).
Un attributo descrittivo contiene informazioni non utilizzabili per effettuare aggregazioni, ma che si ritiene comunque utile mantenere. La traduzione dipende da dove è collegato:
Nell'esempio delle slide, il peso di un prodotto (attributo descrittivo del prodotto) finisce nella dimension table dei prodotti; l'indirizzo e il telefono del negozio, anch'essi descrittivi, nella dimension table dei negozi; il capo reparto e il responsabile del gruppo di marketing, collegati ad attributi di gerarchia, restano nelle dimension table che contengono reparto e gruppo di marketing.
Alcune porzioni delle gerarchie possono essere opzionali. Nella dimension table, nelle righe per cui non è definito un valore, viene inserito un valore fittizio — NULL oppure NON APPLICABILE.
L'opzionalità di un'intera gerarchia NON può essere gestita introducendo un valore nullo nella chiave esterna della fact table: i vincoli di integrità referenziale lo vieterebbero. Occorre invece inserire un'intera tupla fittizia nella dimension table, e far puntare a essa le righe della fact table per cui la gerarchia non è definita. È il caso della promozione nello schema VENDITA: per le vendite senza promozione si imposta la chiave della promozione alla tupla fittizia.
Dato il costrutto DFM, scegliete la traduzione logica corretta.
Se una gerarchia si presenta più volte nello stesso fatto (o in due fatti diversi) non conviene introdurre copie ridondanti delle relative dimension table. Due casi:
ID_Chiamante sia ID_Chiamato;Gli attributi di convergenza — più percorsi di dipendenze funzionali che entrano in uno stesso attributo — si includono nella stessa dimension table dei loro attributi padri, senza particolari accorgimenti. Nell'esempio delle slide, la convergenza su categoria (raggiunta sia da tipo sia da marca) si traduce semplicemente mettendo categoria, tipo e marca nella medesima dimension table dei prodotti.
Dal punto di vista concettuale, un attributo cross-dimensionale b definisce un'associazione molti-a-molti fra due o più attributi dimensionali a₁…aₘ. La sua traduzione a livello logico richiede l'inserimento di una nuova tabella che includa b e abbia come chiave gli attributi a₁…aₘ.
L'esempio delle slide è l'IVA: l'aliquota dipende dalla coppia (categoria del prodotto, stato del negozio) — una dipendenza che attraversa due dimensioni. La tabella IVA ha come chiave (categoria, stato) e contiene l'aliquota; la fact table non cambia, e l'aliquota si recupera con un join aggiuntivo quando serve.
L'arco multiplo — l'attributo terminale raggiunto da più valori per ogni evento — è il costrutto con la traduzione più delicata. La soluzione più ovvia è inserire una tabella aggiuntiva, la bridge table:
La soluzione con bridge table rende possibili due tipi di interrogazioni:
Incasso × Peso;Nel caso si voglia continuare a utilizzare lo schema a stella, è necessario rendere più fine la granularità del fatto, modellando così l'arco multiplo direttamente nella fact table (push-down). Questa soluzione richiede l'aggiunta alla fact table di una nuova dimensione corrispondente all'attributo terminale dell'arco multiplo: la fact table delle vendite dei libri acquisisce la chiave dell'autore e le sue righe vengono replicate tante volte quante sono le corrispondenze dell'arco multiplo.
| Push-down | Bridge table | |
|---|---|---|
| Potere informativo | Identico nelle due soluzioni | |
| Ridondanza | Forte: le righe della fact table sono replicate tante volte quante sono le corrispondenze dell'arco | Nessuna ridondanza nella fact table |
| Il peso | Codificato permanentemente nella fact table; l'aggiornamento può risultare molto complesso | Attributo della bridge table, aggiornabile separatamente |
| Interrogazioni di impatto | Molto complesse | Semplici |
| Costo di esecuzione | Ridotto grazie al minor numero di join | Ridotto a causa del minor numero di tuple coinvolte |
| Calcolo degli eventi pesati | Durante l'alimentazione | Durante l'interrogazione |
Il confronto delle due soluzioni è materia d'esame: i pro e i contro di push-down e bridge table vengono chiesti di frequente, e l'occupazione di memoria delle due alternative è un esercizio classico (lo rivedremo nella sezione 16 con il caso RICOVERO, dove ogni ricovero è caratterizzato in media da 3 diagnosi).
Questo termine indica una dimensione la cui gerarchia contiene un solo attributo. Se la lunghezza dell'attributo non è eccessiva, può convenire evitare la creazione di una specifica dimension table, importando direttamente i valori dell'attributo nella fact table.
Per esempio, nel data mart degli ordini le dimensioni degeneri tipiche sono lo stato della linea d'ordine, la modalità di spedizione e il codice di ritorno: gerarchie di un solo attributo, con pochi valori possibili. Creare per ciascuna una dimension table costerebbe una chiave surrogata in più nella fact table per ogni riga, senza alcun beneficio: meglio importare direttamente i valori.
Una soluzione alternativa è utilizzare un'unica dimension table per modellare più dimensioni degeneri — la junk dimension:
Perché una junk dimension conviene? Con tre dimensioni degeneri separate, la fact table importerebbe tre chiavi surrogata (4 byte ciascuna, per ogni riga); con la junk dimension ne importa una sola, e i valori delle tre dimensioni degeneri sono pagati una volta sola nella junk table — le cui righe sono poche (il prodotto delle cardinalità). Il confronto numerico è un esercizio d'esame ricorrente, che affronteremo nella sezione 16.
La junk dimension funziona solo quando il numero di valori distinti è limitato: se una delle dimensioni degeneri ha migliaia di valori (per esempio un codice di tracciamento), il prodotto delle cardinalità esplode e la junk table diventerebbe più grande della fact table stessa. In quel caso la dimensione degenere va importata direttamente nella fact table — e le altre, eventualmente, nella junk.
Questo termine indica una gerarchia in cui per alcune istanze risultano assenti uno o più livelli di aggregazione. Vengono gestite a livello estensionale, inserendo opportuni valori fittizi.
Il problema è più complesso rispetto al caso degli attributi opzionali, poiché la mancanza di un valore di un attributo non implica la mancanza dei successivi nella gerarchia di aggregazione: San Marino non ha la provincia, ma ha la nazione. È esattamente questo «buco in mezzo» a rendere delicata la consistenza dell'operatore di roll-up.
L'esempio canonico è la gerarchia geografica comune → provincia → regione → nazione, dove i comuni di San Marino e Città del Vaticano non hanno provincia. Sono possibili tre soluzioni (bilanciamenti), che si differenziano per il tipo di segnaposto inserito:
Questo termine indica una gerarchia in cui il numero dei livelli di aggregazione non è codificabile nello schema e può variare da istanza a istanza. Non può essere modellata tramite schema a stella.
L'esempio classico è la gerarchia degli impiegati (chi è responsabile di chi): un impiegato può avere subordinati che a loro volta ne hanno, e la profondità non è nota a priori. Le slide propongono due soluzioni.
Una possibile soluzione prevede l'utilizzo di un autoanello: la dimension table Impiegato contiene una chiave esterna verso se stessa (ID_Responsabile), che punta al record dell'impiegato di cui si è subordinati. È semplice, ma non sempre gestibile in modo ottimale con i DBMS commerciali — e soprattutto SQL non è un linguaggio ricorsivo: percorrere la catena di responsabilità richiederebbe un numero di self-join pari alla profondità, che non è noto.
Una soluzione più potente prevede di appiattire la gerarchia, esplicitando tutti i legami da essa indotti in una tabella di navigazione con gli attributi ID_Padre, ID_Figlio, Livello e Foglia:
Notate l'ultima osservazione delle slide: escludendo dai join la tabella di navigazione si continua ad avere uno schema a stella. La tabella di navigazione è un'appendice opzionale: chi non interroga la gerarchia ricorsiva non la tocca, e lo schema resta relazionale puro.
Chiudiamo il capitolo con lo strumento quantitativo che gli esercizi d'esame richiedono in continuazione: la stima dell'occupazione di memoria di una soluzione di progetto logico. Le regole sono poche:
Uno schema di fatto ORDINE (2.000.000 di eventi primari) include tre dimensioni degeneri: statoOrdine (4 byte, 6 valori), tipoSpedizione (10 byte, 4 valori), resoY/N (1 byte). Senza junk dimension si valuta ogni dimensione degenere separatamente: statoOrdine conviene direttamente nella fact table (2M × 4 = 8.000.000, contro i 8.000.048 di una tabella dedicata); tipoSpedizione conviene con dimension table (2M × 4 + 4 × (4+10) = 8.000.056, contro i 20.000.000 del valore in fact table); resoY/N direttamente in fact table (2M × 1 = 2.000.000). Totale: 18.000.056. Con junk dimension: una sola chiave surrogata in fact table (2M × 4 = 8.000.000) più la junk table con tutte le combinazioni: (4+4+10+1) × (6 × 4 × 2) = 19 × 48 = 912. Totale: 8.000.912. La junk dimension occupa circa 2,2 volte meno — la lezione generale: per ogni dimensione degenere si confronta il costo del valore in fact table con quello della chiave surrogata più la tabella, e la junk conviene quando le combinazioni sono poche.
Confrontate l'occupazione delle due soluzioni per le dimensioni degeneri dell'ORDINE.
Due casi d'esame aggiuntivi, che ricorrono identici negli anni:
Questi calcoli chiudono la progettazione logica nel suo primo tempo: schema scelto, costrutti tradotti, memoria stimata. Il secondo tempo — viste materializzate, scenari temporali, frammentazione — è il capitolo 12.
Il MOLAP memorizza i dati con strutture intrinsecamente multidimensionali (vettori multidimensionali): soluzione naturale con ottime prestazioni, ma afflitta dalla sparsità (solo ~20% delle celle informative), dalla mancanza di strutture standard (strutture proprietarie) e dalla riluttanza di chi ha vent'anni di esperienza relazionale. Il ROLAP usa il modello relazionale con lo schema a stella: è la soluzione della maggior parte dei sistemi, soprattutto di grandi dimensioni. Il HOLAP combina i due: DW ROLAP per enormi quantità di dati, DM MOLAP per la velocità di accesso, cubi MOLAP «al volo» per il what-if.
Con due tecniche: la suddivisione delle dimensioni, che partiziona il cubo in chunk gestiti diversamente a seconda che siano densi o sparsi; e la compressione dei chunk sparsi, che rappresenta il solo offset delle celle che contengono informazioni.
Un insieme di dimension table DT₁…DTₙ, ciascuna con chiave primaria (tipicamente surrogata) e attributi a diversi livelli di aggregazione, più una fact table FT che importa le chiavi di tutte le dimension table, ha come chiave primaria l'insieme delle chiavi esterne e contiene un attributo per ogni misura. Le dimension table sono completamente denormalizzate: un solo join per dimensione; il costo è la ridondanza. Non ci sono problemi di sparsità, perché si memorizzano solo tuple corrispondenti a eventi esistenti.
Lo schema a fiocco di neve riduce la denormalizzazione delle dimension table eliminando alcune dipendenze transitive. Le dimension table sono primarie (le cui chiavi sono importate nella fact table) e secondarie (le rimanenti). Riduce lo spazio, ma richiede nuove chiavi surrogate, avvantaggia le interrogazioni sui soli attributi delle dimension table primarie e rallenta quelle che coinvolgono attributi delle secondarie.
(1) Rapporto elevato tra le cardinalità della dimension table primaria e secondaria (forte risparmio di spazio); (2) porzione di gerarchia comune a più dimensioni (la tabella secondaria si riutilizza); (3) presenza di viste aggregate (la secondaria della vista primaria coincide con la primaria della vista secondaria); (4) parte della gerarchia soggetta a frequenti aggiornamenti (l'aggiornamento si isola in una tabella piccola).
Creare una fact table contenente tutte le misure e gli attributi descrittivi direttamente collegati con il fatto e, per ogni gerarchia, creare una dimension table che ne contiene tutti gli attributi. I costrutti avanzati del DFM (capitolo 8) richiedono poi trattazioni specifiche.
Un attributo descrittivo collegato a un attributo dimensionale va incluso nella dimension table che contiene quell'attributo; se collegato direttamente al fatto, nella fact table. Un arco opzionale si gestisce con un valore fittizio (NULL o NON APPLICABILE) nelle righe in cui il valore non è definito. L'opzionalità di un'intera gerarchia non può essere gestita con un NULL nella chiave esterna della fact table (vincoli di integrità): si inserisce un'intera tupla fittizia nella dimension table.
Le gerarchie condivise con gli stessi attributi si traducono importando due volte la chiave della medesima dimension table; se condividono solo una parte, si duplicano con ridondanza oppure si applica uno snowflake sul primo attributo condiviso. Le convergenze si includono nella stessa dimension table dei loro attributi padri. Gli attributi cross-dimensionali richiedono una nuova tabella che li contenga con chiave a₁…aₘ (esempio: la tabella IVA con chiave categoria–stato).
La bridge table, con chiave pari alla combinazione degli attributi collegati all'arco e un eventuale peso: consente interrogazioni pesate (effettivo totale) e di impatto (valori più elevati), il peso si aggiorna separatamente e il calcolo degli eventi pesati avviene in interrogazione. Il push-down rende più fine la granularità del fatto aggiungendo una dimensione per l'attributo terminale: forte ridondanza (righe replicate), peso codificato permanentemente (aggiornamento complesso), interrogazioni di impatto complesse, ma meno join e calcolo degli eventi pesati in alimentazione. Il potere informativo è identico.
Una dimensione degenere è una dimensione la cui gerarchia contiene un solo attributo; se l'attributo non è troppo lungo, conviene importarlo direttamente nella fact table invece di creare una dimension table. La junk dimension è un'unica dimension table che modella più dimensioni degeneri: non esistono dipendenze funzionali fra gli attributi, quindi tutte le combinazioni sono valide; è attuabile solo quando il numero di valori distinti è limitato. Converte tre chiavi surrogata in una sola, pagando una volta sola le combinazioni.
Inserendo valori fittizi (gestione estensionale). Tre bilanciamenti: per esclusione (segnaposto generico «altro»; preferibile con molti dati mancanti; viola la semantica del roll-up); verso il basso (si ripete il valore precedente; preferibile con pochi dati mancanti; report con valori fuori livello); verso l'alto (si ripete il valore successivo; preferibile con molti dati mancanti; report più leggibili).
Non è modellabile con uno schema a stella, perché il numero di livelli non è codificabile e SQL non è ricorsivo. Due soluzioni: l'autoanello (chiave esterna verso se stessa, ID_Responsabile) — semplice ma non sempre gestibile in modo ottimale; la tabella di navigazione che appiattisce la gerarchia esplicitando tutti i legami (ID_Padre, ID_Figlio, Livello, Foglia) — più potente, ma cresce in modo esponenziale con la profondità. Escludendo la tabella di navigazione dai join si continua ad avere uno schema a stella.
Con tre ingredienti: il numero di tuple (eventi primari per la fact table, cardinalità per le dimension table), la lunghezza delle tuple (attributi: lunghezza dichiarata, tipicamente 20 o 50 byte; chiavi surrogate: 4 byte), e la regola occupazione = numero di tuple × lunghezza. Le alternative si confrontano: junk dimension vs dimensioni separate, bridge table vs push-down, punti di snowflaking diversi.