Progettare un datawarehouse moderno
Principali sfide e considerazioni
Introduzione
Ciao, questo è il mio primo post su medium, per cui colgo l’occasione per presentarmi.
Lavoro come Data Engineer presso Quantyca, una società di consulenza che opera nel campo del data management: integrazione di dati e di sistemi, architetture di data bus e big data, business intelligence, analytics. In particolare, ricopro il ruolo di Architect negli ambiti di data integration, datawarehouse e data streaming. Per chi fosse interessato a conoscerci meglio, consiglio una visita al nostro sito web: Quantyca — Data At Core.
In questo post vorrei presentare una panoramica di alcuni aspetti che dovrebbero contraddistinguere un datawarehouse moderno, rimandando al celebre “The Data Warehouse Toolkit: The Definitive Guide to Dimensional Modeling, 3rd Edition” di M.Ross e R.Kimball i lettori interessati ad un approfondimento sulla teoria classica di progettazione di datawarehouse che si è consolidata negli anni.
Rispetto all'epoca in cui è stata formulata la teoria classica dei datawarehouse, il mondo digitale è fortemente cambiato: l’avvento dei big data ha portato con se nuove sfide nella gestione del dato durante il suo ciclo di vita. I volumi di informazioni generati oggi sono aumentati in modo esponenziale rispetto a un decennio fa e i dati da dover processare, analizzare e presentare sono sempre più eterogenei: ai tradizionali formati relazionali si sono affiancati i sempre più diffusi formati semi-strutturati o non strutturati, dovuti alla crescita dell’Internet of Things; la diffusione dei social network ha portato alla generazione di dati multimediali e sempre più ad alta frequenza.
Ad oggi sono sempre più comuni scenari in cui il datawarehouse non rappresenta più l’unico sistema target verso cui tutti i flussi ETL sono diretti, ma fa parte di un ecosistema più ampio, comprendente numerosi sistemi e tecnologie eterogenee, che formano un’architettura poliglotta.
Questi nuovi scenari richiedono una revisione dei principi fondamentali della teoria classica di sviluppo dei datawarehouse, per poter far fronte alle esigenze di performance, rapidità di utilizzo e versatilità richieste oggi.
Nel post propongo alcune possibili strategie di design del modello dati, con lo scopo di ottenere maggiori performance dal punto di vista dell’utilizzatore del sistema. In seguito, propongo una visione di come è possibile collocare il datawarehouse nell'architettura dati poliglotta e come permetterne l’interoperabilità con gli altri sistemi, presentando possibili casi d’uso sulla base dell’esperienza progettuale.
Modello dati consistente ma funzionale all'analisi
Nella teoria classica di progettazione di datawarehouse, le tabelle dei fatti sono pensate per contenere fondamentalmente due tipi di informazioni: un primo insieme di campi è composto dalle chiavi esterne, che permettono di recuperare le informazioni anagrafiche e di contesto associate al record del fatto, tramite operazione di join con le relative tabelle dimensionali; un secondo gruppo di campi è costituito dai valori numerici, categorici o booleani delle misure che descrivono l’evento accaduto (ad esempio, il prezzo di una vendita, il tipo di una valuta, un flag di attivazione/disattivazione).
Le informazioni descrittive che costituiscono il contesto in cui è avvenuto l’evento rappresentato dal fatto sono invece contenute nelle tabelle dimensioni.
Per ragioni di performance, può risultare conveniente “replicare” alcuni attributi dimensionali di grande importanza per l’analisi anche sulle tabelle dei fatti a cui quelle informazioni di contesto fanno riferimento. In questo modo si abilita la possibilità di un’interrogazione immediata un’unica tabella, la tabella fatto, evitando di dover agganciare in join le tabelle dimensionali sulla chiave esterna, per recuperare le informazioni di contesto di interesse: la query risultante è più performante, richiede meno risorse macchina e minor tempo di esecuzione.
Benché la ridondanza dei dati sia stata storicamente vista con scetticismo dai database designer, che la indicano come una possibile causa di inconsistenza, un approccio di questo tipo può essere applicato per i campi dimensionali più rilevanti e usati nella maggior parte delle analisi, a patto di sviluppare dei flussi di alimentazione robusti, che garantiscano la consistenza e che controllino di produrre lo stesso valore in tutte le tabelle nelle quali la stessa informazione viene rappresentata.
Modello dati user-friendly
Un altro aspetto su cui pensare ad un’evoluzione è il tema della definizione delle chiavi primarie. Come illustrato nel manuale “The Data Warehouse Toolkit: The Definitive Guide to Dimensional Modeling, 3rd Edition”, nella teoria classica si sosteneva l’opportunità di utilizzare come chiavi primarie le cosiddette chiavi surrogate, valori interi univoci non parlanti, cioè privi di alcun valore semantico, ad esempio prodotti da funzioni generatrici di sequenze numeriche. La ragione alla base di questo principio era principalmente tecnica: i primi DBMS mostravano una maggior efficienza nel gestire operazioni di join su campi interi rispetto che su valori contenenti codici alfanumerici.
Inoltre, vi erano anche motivazioni legate alla manutenzione delle chiavi, considerando la possibilità che le chiavi naturali potessero essere soggette a cambiamenti per motivi di business, su cui però evito di soffermarmi, perché con l’esperienza progettuale si è visto che non sempre la visione data dalla teoria rispecchia quello che avviene nella pratica, nella gestione del day-by-day di un sistema. Si può dire che, su questo punto, che si tratta molto di orientamenti “filosofici”.
Invece, in coerenza con il filo conduttore del post, preferisco soffermarmi sull'aspetto legato alla facilità e alla rapidità di utilizzo, sia a livello di performance di elaborazione, sia a livello di comprensibilità umana.
Con l’evoluzione delle tecnologie di database colonnari, la differenza di performance tra eseguire delle join su chiavi intere surrogate piuttosto che su chiavi naturali (eventualmente di tipo diverso da integer) è divenuta trascurabile.
Nella nostra esperienza progettuale si è visto che la definizione di chiavi naturali semanticamente parlanti come chiavi primarie delle tabelle porta ad una maggior immediatezza di comprensione e di consultazione del database, non solo programmatica ma anche interattiva, rendendo le analisi “on the fly” più agevoli ed evitando scomodi processi di decodifica.
Consideriamo un modello dati di esempio basato sulle chiavi surrogate, come mostrato in figura seguente.
Ipotizziamo di voler calcolare il totale delle vendite avvenute nel negozio STOR1 per i prodotti PROD1 e PROD2: dovremmo scrivere una query come la seguente.
Proviamo ora a cambiare il modello dati, basandolo sulle chiavi naturali e introducendo qualche ridondanza.
Ipotizziamo di voler procedere con la stessa analisi: calcolare il totale delle vendite avvenute nel negozio STOR1 per i prodotti PROD1 e PROD2: con il nuovo modello dati, la query si semplifica in modo significativo.
Le operazioni di join sono scomparse: questo rende più semplice scrivere la query e meno oneroso per il database eseguirla.
In questo semplice caso di esempio sono coinvolte solamente poche tabelle, ma in casi più complessi il vantaggio di evitare o, in generale, ridurre le operazioni di join rende le query più efficienti e più semplici da scrivere e da interpretare.
Un sistema flessibile ma robusto
A differenza di un database transazionale, che ha l’obiettivo di memorizzare i dati garantendone la consistenza e l’integrità, secondo le proprietà ACID, un datawarehouse è finalizzato a rappresentare i dati nel formato più utile all'analisi. Di conseguenza, i requisiti di data quality di un datawarehouse possono essere più rilassati rispetto ad un transazionale, privilegiando la possibilità di avere a disposizione più dati possibili da analizzare.
Un dato parzialmente corrotto o incompleto può risultare comunque utile per alcune analisi, pertanto, può essere conveniente rilassare i vincoli all'ingresso nel sistema e accettare di alimentare il datawarehouse anche con dati non totalmente esatti o contenenti alcuni valori mancanti.
E’ sempre meglio avere momentaneamente un dato incompleto piuttosto che non averlo del tutto: sfruttiamolo per quel che di buono ci può dare.
Dati con simili problematiche devono però essere marcati a livello applicativo con un campo che ne segnali l’incompletezza; la logica di alimentazione deve essere in grado di re-importare periodicamente i dati problematici nel tentativo di bonificarli. Infatti, spesso l’incompletezza di un dato è dovuta alla momentanea mancanza di informazioni di contesto, dovuta a ritardi di inserimento nella sorgente o a problemi di sincronizzazione dei flussi, il che rende molto probabile che la problematica si risolva in un secondo momento.
Come esempio, consideriamo il caso il caso in cui un nuovo cliente di un negozio online si registra sul sito di vendita e-commerce; immediatamente dopo, il nuovo cliente effettua un ordine. Può capitare che l’informazione sull'ordine effettuato sia immediatamente registrata e consegnata al datawarehouse da un flusso di integrazione streaming, mentre le informazioni anagrafiche del cliente siano importate nel datawarehouse da flussi batch schedulati a frequenza più bassa. Nel periodo transitorio che precede l’arrivo delle informazioni anagrafiche del cliente nel sistema, l’informazione sull'ordine effettuato può essere già utilizzata per aggiornare la somma parziale giornaliera delle vendite, senza dover necessitare delle informazioni anagrafiche del cliente che lo ha effettuato, che saranno invece utili per altri tipi di analisi. Nel momento in cui questi dati saranno importati, si procederà all'aggiornamento delle informazioni dell’ordine con l’integrazione dei dati del cliente.
Pertanto, quello che proponiamo è un approccio innovativo rispetto al passato: un approccio basato sull'identificazione e la gestione delle anomalie piuttosto che su una politica di rigetto del dato corrotto.
Un sistema frequentemente aggiornato
Oltre ai punti fin qui discussi, il vero valore aggiunto di un datawarehouse moderno è la sua frequenza di aggiornamento. I datawarehouse tradizionali erano alimentati con frequenza per lo più giornaliera, in modalità batch.
Oggigiorno viviamo in un mondo caratterizzato da una generazione di dati continua, dovuta sia a processi manuali sia al normale funzionamento di dispositivi automatici (si pensi ai sensori e all’IOT). La richiesta di analisi in real time è sempre più pressante. Il dato è tanto utile quanto più è attuale: rispetto anche solo a qualche anno fa, il dato diventa più velocemente obsoleto, perdendo gran parte del suo valore.
Pertanto, un datawarehouse rappresenta davvero un valore per il business se è continuamente aggiornato e in linea con la situazione degli eventi in tempo reale, o comunque rappresentativo di uno snapshot il più possibile recente.
La strategia di alimentazione classica basata su elaborazioni batch rappresenta un limite per un aggiornamento frequente. Pertanto, è conveniente migrare verso un’alimentazione realizzata da flussi ad alta frequenza, schedulati ogni 10–15 minuti, che operino su microbatch, ossia insiemi di dati più ridotti, che richiedano minor tempo di elaborazione e minor occupazione di risorse di calcolo. Schedulando i flussi di alimentazione nell'ordine dei minuti, i dati nuovi da processare nella singola esecuzione sono in quantità minore rispetto a schedulare le esecuzioni a distanza di ore. In questo modo si ottiene un datawarehouse contenente una fotografia maggiormente aggiornata dei dati, rispetto all'alimentazione a batch.
Inoltre, qualora l’insieme dei dati da inserire nel datawarehouse sia ingente, ad esempio nei casi di “carico iniziale” del sistema, è conveniente impostare una suddivisione del working set di dati da elaborare in sottoinsiemi più piccoli, da processare uno alla volta in modo iterativo, per ricondurre quella che sarebbe un’alimentazione batch ad un’alimentazione microbatch.
Nei casi in cui i requisiti RT siano più stringenti, può essere necessario cambiare completamente paradigma, adottando una modalità streaming, che richiede l’introduzione di tecnologie di message broker (data bus) e di stream processing. Le streaming platform abilitano la possibilità di processare i dati per singolo record, ottenendo una latenza infinitesima e un aggiornamento del datawarehouse in near real time, ossia nell'ordine dei secondi.
Design multi-livello
L’efficacia di un datawarehouse dipende molto da come è organizzato, sia a livello logico che a livello fisico. Illustriamo questo assunto basandoci su un caso pratico.
Consideriamo lo scenario in cui si deve esporre all'analisi un modello dimensionale che rappresenta il venduto di una multinazionale. Il gruppo dispone di negozi dislocati in diversi Paesi e aventi motori di cassa differenti, in base alla rispettiva nazione. I dati prodotti e inviati al quartier generale dai diversi sistemi di cassa sono inevitabilmente in formati differenti, pur rappresentando tutti il medesimo set di informazioni.
L’obiettivo è alimentare un unico datawarehouse che esponga la totalità dei dati in formato uniforme e adatto per eseguire analisi sul venduto giornaliero, così come sul venduto degli ultimi N mesi rolling, entrambi confrontati con il venduto nel periodo corrispondente dell’anno precedente.
Una strategia di design del datawarehouse che si è dimostrata efficace consiste in una strutturazione multi-livello: dal basso verso l’alto, il sistema viene stratificato in diversi livelli logici, in cui il dato, passando ai livelli superiori, si allontana sempre più dal formato sorgente per conformarsi in una cosiddetta vista comune e assumere la modellazione dimensionale a fatti e dimensioni, per poi culminare in un datamart che esponga delle metriche aggregate pronte per certi tipi di analisi.
Un simile design è illustrato in figura seguente.
Entriamo nel dettaglio dei singoli livelli.
REP: nel livello di “replica” i dati vengono importati senza alcuna trasformazione di formato rispetto a come vengono prelevati dai rispettivi sistemi sorgente, per mantenere nel datawarehouse una copia fedele del dato originale. Pertanto, nel caso in cui i dati provengano da N sistemi sorgenti, si avranno N modelli diversi a livello di replica.
ODS: nel livello di “operational data store” i dati subiscono una fase di cleaning e vengono trasformati per aderire ad un formato uniforme, attraverso un mapping tra le informazioni dei vari formati sorgenti e l’unica “vista comune” che si vuole ottenere. I dati rimangono ancora in un formato transazionale: non vengono ancora introdotte le entità fatti e dimensioni.
DWH: nel livello di “datawarehouse” vero e proprio, si trasforma il dato per portarlo ad una rappresentazione a stella o a fiocco di neve, arricchendolo con le informazioni dimensionali. A questo livello è conveniente prevedere una parziale replicazione dei dati, come discusso in precedenza, e il giusto grado di de-normalizzazione in funzione della fruizione da parte dei tool di analisi e dell’utente in modalità interattiva.
DMT: nel livello più alto, quello di “datamart”, vengono costruite delle “viste” aggregate, che espongono metriche pronte in base ai tipi di report da generare, ad esempio, metriche di totale venduto sugli ultimi N mesi rolling.
Ciascun livello logico si traduce, a livello fisico, in un corrispondente schema del database, con le rispettive strutture. Ciascun livello conterrà lo storico dei dati nel formato specifico per il livello in questione: pertanto, è conveniente prevedere uno schema di staging per ciascun livello, che conterrà strutture “gemelle” rispetto allo schema “finale”; le strutture di staging saranno utilizzate come tecnicismo per applicare le trasformazioni sul dataset dell’elaborazione corrente, a valle delle quali il dataset trasformato sarà “riversato” nello schema finale, che contiene lo storico dei dati.
Il consolidamento dei dati da un livello logico a quello superiore è realizzato da flussi ETL-ELT che effettuano elaborazioni e arricchimento sui dati, appoggiandosi sulle strutture di staging, prima di riversare i nuovi dati elaborati nello storico dei dati già processati.
Con l’esperienza progettuale si è osservato che una simile implementazione del consolidamento dei dati si è rivelata altamente performante: le logiche (potenzialmente complesse) sono applicate in modo isolato sul dataset corrente utilizzando tabelle di staging; il risultato delle elaborazioni sul dataset corrente viene riconciliato con il resto dei dati già presenti, scegliendo il tecnicismo più performante possibile in base alla tecnologia utilizzata, considerando che l’operazione di riconciliazione può essere di per se onerosa perché può prevedere sia insert di nuovi dati sia eventualmente update di dati esistenti (in rari casi anche delle delete di dati non più validi).
Il datawarehouse nell'ecosistema dati
Come anticipato nell'introduzione, la collocazione del datawarehouse all'interno dell’architettura poliglotta di integrazione ed elaborazione dati ha subito un’evoluzione negli ultimi anni, dovuta alla diffusione sempre più rilevante dei big data.
Nello scenario più semplice, il datawarehouse è adottato come unico sistema in cui raccogliere e storicizzare grosse moli di dati in un formato funzionale all'analisi. I dati sorgente possono provenire da molteplici sistemi sorgente, in cui potenzialmente sono salvati in formati differenti. Flussi ETL o ELT di tipo batch (sempre più microbatch, come discusso nella sezione precedente) operano trasformazioni e arricchimenti sui dati sorgente, li convertono in un formato uniforme per la destinazione e li consolidano nel modello dati progettato e implementato nel DBMS analitico scelto come datawarehouse.
Un panorama più ricco prevede sempre il datawarehouse come unico sistema destinazione dei dati, ma alimentato da una compresenza di flussi di tipo microbatch e di flussi di tipo streaming, per adattarsi alle diverse esigenze di real time delle varie entità logiche persistite nel datawarehouse. In un simile scenario, tecnologie differenti vengono adottate per lo sviluppo dei flussi: tipicamente, tool di ETL-ELT per i microbatch, tool di message broker e streaming platform per i flussi real time.
Ampliando ulteriormente l’ecosistema dati, in certe applicazioni il datawarehouse non risulta più l’unico sistema destinazione dei dati per l’analisi, ma uno tra N sistemi, ciascuno dei quali assolve alla sua funzione, che necessitano di scambiarsi dati e comunicare in modo unidirezionale o anche bidirezionale tra loro. In un’architettura di questo tipo, il ruolo centrale viene assunto dal data bus, che si pone come broker di tutti i flussi di interconnessione tra i vari sistemi. Il singolo sistema, in questa visione, non svolge più un solo ruolo di sorgente o destinazione, ma potenzialmente può ricoprirli entrambi: il sistema può ricevere dati, elaborarli e inviare i dati elaborati al sistema successivo, formando così una pipeline di elaborazione, o a N sistemi consumatori, come nel caso della streaming platform.
Un esempio pratico può essere il caso in cui i dati vengono persistiti e storicizzati in un datalake, dove tramite framework di calcolo distribuito subiscono elaborazioni massive; gli stessi dati (sorgenti oppure risultato dell’elaborazione dentro al datalake) vengono inviati al datawarehouse per la fruizione da parte dei tool di front-end.
Un’ulteriore utilità del datalake si presenta nel caso in cui moli di dati ingenti necessitano di essere persistiti senza avere grande impatto su costi di licenza, che invece caratterizzano fortemente lo storage all'interno di un DBMS analitico. La soluzione può prevedere allora l’impiego del datalake per la conservazione della totalità dei dati, mentre il datawarehouse è alimentato con i soli dati più recenti, di interesse per la finestra di analisi.
Scelta tecnologica moderna
Al giorno d’oggi diversi vendors di database analitici forniscono delle features native per l’integrazione dati in input e output con tecnologie differenti, che costituiscono gli altri componenti dell’architettura (ad esempio Apache Hadoop, Apache Spark, Apache Kafka).
Inoltre, dopo anni di evoluzione tecnologica nell'ambito dei database analitici, si è distinta particolarmente la tecnologia di database column-oriented, che va oggi per la maggiore nella scelta di uno specifico DBMS da adottare per il datawarehouse, per via delle migliori performance in risposta a carichi OLAP (aggregazioni, join in lettura su grosse moli di dati).
Tuttavia, simili features offerte dalle tecnologie moderne non bastano a garantire le performance desiderate, se non accompagnate da strategie di design del database e del modello dati da implementare che ne sfruttino il potenziale.
Conclusioni
Per riassumere, l’efficienza e l’efficacia di un datawarehouse a rispondere alle esigenze di business di oggi dipende da diversi fattori.
Un impatto determinante sulle performance è dovuto alla strategia di progettazione del modello dati: è importante pensare le strutture in funzione anche delle interrogazioni più ricorrenti che saranno eseguite su di esse.
E’ importante progettare e implementare un sistema versatile ad acquisire dati eterogenei, in formati differenti, anche parzialmente incompleti o anomali, che sappia gestire le eccezioni a livello applicativo e che sfrutti dai dati acquisiti il massimo valore che si può ricavare da essi.
Il sistema deve essere frequentemente aggiornato per descrivere in tempo reale il valore dei dati prodotti, considerando che oggigiorno il dato perde velocemente valore in poco tempo: un dato relativo a qualche ora prima o addirittura al giorno prima risulta già obsoleto e di poca utilità, per molte applicazioni.
La progettazione multi-livello è un pattern consolidato che si è rivelato affidabile: la sfida risiede nell'ottimizzare le performance di consolidamento dei dati da un livello a quello superiore, facendo uso di strutture di staging e rendendo poco onerosa la riconciliazione dei nuovi dati con quelli storici.
Le caratteristiche del mondo digitale di oggi richiedono di avere una visione ampia dell’ecosistema dati, in cui il datawarehouse è solamente uno degli attori in gioco e deve prevedere una comunicazione bidirezionale con gli altri sistemi. A questo proposito, la scelta di tecnologie di DBMS moderne che forniscano features di integrazione native con altri tool risulta essere un fattore determinante che contribuisce all'efficacia del sistema.
Se ti è piaciuto questo post e sei interessato alle nostre attività, seguici su Linkedin!