Scarica BIG DATA ENGINEERING (prof. Storti) e più Appunti in PDF di Database Distribuiti solo su Docsity!
BIG DATA
I Big Data sono quei dati che non possono essere gestiti con le tecnologie tradizionali utilizzate fino a poco tempo fa. In altre parole, si parla di Big Data quando un singolo computer non è in grado di elaborare l'enorme mole di dati disponibile. Unità di misura L’aumento della produzione di dati è contestuale alla diminuzione del costo di hardware dove immagazzinarli e gestirli. 4V DEI BIG DATA
- Volume
- Variety à ogni tipo di dato ha un database specifico dove essere memorizzato (es. il testo non verrà memorizzato in una tabella)
- Velocity
- Veracity à quanto i dati sono affidabili La Quinta V: Il Valore Oltre ai quattro attributi tradizionali dei big data (Volume, Velocità, Varietà e Veracità), si aggiunge una quinta "V", ovvero Valore. La raccolta di grandi quantità di dati è inutile se non si ha chiaro quale valore possano generare o come possano essere utilizzati. Il valore dei dati è strettamente legato alla loro qualità (Veracità): dati di bassa qualità possono produrre poco valore, compromettendo l'analisi e l'interpretazione. Il Processo dei Big Data
- Acquisizione : Raccolta dei dati da varie fonti, che possono includere sensori, dispositivi, social media, siti web e altre piattaforme digitali.
- Estrazione : Processo di estrazione delle informazioni rilevanti dai dati grezzi, selezionando le parti utili per l'analisi.
- Integrazione : Unione di fonti di dati diverse, combinando dati strutturati e non strutturati per ottenere un quadro più completo.
- Analisi : Esecuzione di analisi approfondite sui dati integrati per estrarre modelli, tendenze e informazioni significative.
- Decisione : Uso dei risultati dell'analisi per prendere decisioni informate, migliorare processi aziendali o creare nuove opportunità di business. Rischi e Sfide nei Big Data
- Privacy : La riservatezza dei dati è un tema cruciale, poiché sempre più dati personali vengono conservati da aziende per profilare i clienti. Regolamentazioni come il GDPR mirano a garantire che la memorizzazione e la gestione dei dati nei sistemi cloud avvengano in modo sicuro e rispettoso dei diritti individuali.
- Comprensione dell'Output : Un rischio comune è quello di interpretare male i risultati dell'analisi dei dati. È facile cadere nell'errore di vedere correlazioni tra
fenomeni che in realtà non hanno una relazione causale. Un esempio classico è la correlazione tra il numero di matrimoni e il numero di persone che annegano, una coincidenza che non implica alcun legame diretto. Quali sono i limiti dei database relazionali? Il relazionale ha funzionato molto perché si tratta di un modello formale (quindi affidabile – relazione, algebra) ma anche intuitivo (tabella). Il linguaggio di query è relativamente semplice da apprendere. Inoltre, la gestione efficiente dell'integrità dei dati, ad esempio tramite le chiavi esterne (foreign key), garantisce la persistenza e la coerenza dei dati. Con l'avvento e l'evoluzione del web, tuttavia, l'approccio relazionale non è più sufficiente, per diverse ragioni:
- Tipologia delle applicazioni : inizialmente erano transazionali, mentre oggi includono motori di ricerca e altre tipologie più complesse.
- Tipo di operazioni : si è passati da un modello prevalentemente incentrato su lettura e scrittura a uno basato su lettura e ricerca.
- Numero di utenti : da poche unità locali a milioni di utenti distribuiti in tutto il mondo.
- Volume dei dati : il volume delle informazioni da gestire è cresciuto esponenzialmente.
- Regolarità delle operazioni : prima erano prevedibili, mentre ora la frequenza delle operazioni è variabile (ad esempio, gli ordini su e-commerce possono avvenire in orari molto diversi tra loro).
- Stabilità delle operazioni : se un tempo le operazioni erano stabili, oggi devono supportare un'elevata velocità e flessibilità. Esiste un'altra serie di limiti del modello relazionale. Nei database relazionali, i dati vengono organizzati in tabelle, ma nei linguaggi di programmazione come Python, i dati vengono spesso gestiti in formati diversi, ad esempio come dizionari, non come tabelle. Questo crea una discrepanza tra la rappresentazione dei dati nel database e il modo in cui vengono utilizzati nel codice. Uno dei limiti principali dei database relazionali è la loro rigidità. Se si dispone di un'informazione aggiuntiva, non è possibile memorizzarla a meno di modificare la struttura della tabella, ad esempio creando una nuova colonna. Questo impone di aderire rigorosamente allo schema definito, il che diventa problematico man mano che i dati diventano meno strutturati. Oggi, adattare continuamente lo schema alle nuove esigenze risulta troppo costoso e inefficiente. Un altro limite riguarda l'architettura su cui si basano i database relazionali. Questi sono progettati per funzionare su un singolo computer, poiché, all'epoca della loro ideazione, non esisteva la possibilità di distribuire il carico su più macchine. L'unico modo per aumentare le prestazioni era quindi attraverso la scalabilità verticale , ossia potenziare l'hardware del singolo computer. Tuttavia, questa soluzione è estremamente costosa. L'alternativa è la scalabilità orizzontale , che prevede l'utilizzo di molti computer più piccoli collegati tra loro, in modo da funzionare come un supercomputer. Questo approccio è più flessibile e sostenibile dal punto di vista economico, poiché consente di aggiungere macchine gradualmente. Tuttavia, i database relazionali non si adattano bene a questo modello, rendendo necessaria l'adozione di tecnologie progettate appositamente per ambienti distribuiti.
Si tratta di un sistema senza nessun tipo di schema, ovvero regole con cui inserire le chiavi, infatti alcuni non li considerano database. Questo tipo di sistemi estremizzano l’idea di flessibilità, abbandonando tutti i principi su cui si basa un dbms, avendo come conseguenza un sistema velocissimo che può funzionare nella ram del computer senza salvare dati sul disco. Nessun dbms complesso lo riesce a battere in velocità. Tuttavia, visto la semplicità del modello si possono eseguire solo operazioni estremamente semplici, infatti non si ha un linguaggio di query ma solo istruzioni elementari per inserire la coppia. Questo significa che devo già sapere qual è la chiave per ottenere il value corrispondente, altrimenti il documento non verrà più recuperato. Per i dbms quello che c’è nel value è qualcosa di ‘oscuro’ ovvero estraneo al dbms, viene considerato solo come un insieme di bit (non lo classifica ad esempio come stringa). Quindi il valore associato a ogni chiave viene per questo chiamato blob binario ‘oscuro’. Alcuni di questi hanno un linguaggio di query, altri con una sintassi diversa permettono di fare dei filtraggi o aggregazioni come in sql. L’unico elemento mancante è il JOIN in quanto problematico in un contesto di distribuzione orizzontale. Quindi consente ricerche per:
- uguaglianza
- indici su più attributi L’idea è di avere un semplice dbms che memorizza coppie ‘nomedelcampo-valore’. Primitivo ma nasce da amazon per supportare i dati relativi ai sessioni dei clienti sul sito. Per memorizzare ciò che l’utente faceva sul sito. Lo scopo è quindi diverso rispetto al solito, era molto semplice perché si vuole memorizzare solo dati temporanei, che durano il tempo della sessione, e sono funzionali a un certo processo (es acquisto prodotto). Es. Memcached Document-based: idea di avere concetto di collezione o raccolta. Quello che è una riga diventa un documento, ovvero un insieme di coppie chiave-valore. La differenza lampante con il primo modello è che le coppie chiave-valore non possono essere raggruppate, mentre qui sì grazie ai documenti, che vanno quindi a raccogliere una serie di chiave-valore che vanno a descrivere un certo oggetto. L’obiettivo è di organizzare i dati avendo a livello esterno una coppia chiave-valore dove il valore è un oggetto ocmplesso che contiene al suo interno altre coppie chiave-valore. È basato su colonne perché le chiavi del valore sono interpretate come colonne di una tabella.
Nel caso di sistemi basati su righe
- Semplicità nell’aggiungere una riga
- Ma sono costretto a leggere tutta la riga Mentre per sistemi basati su colonne
- vengono letti solo dati di interesse
- Però la scrittura richiede più tempo perché devo spezzettare la riga in singoli valori da mettere su più colonne Ottimale per un’applicazione che deve solo leggere, non tanto se si richiedono molte applicazioni di scrittura. Inoltre, normalmente in un database quando si cancella una riga o si modifica un valore, il valore precedente è perso per sempre. Invece questi sistemi mantengono una copia dei valori precedenti, per poter tracciare tutta la storia del dato. Si chiama versioning dei dati. Se io descrivo un cliente per ogni cliente posso inserire un numero diverso di campi, quindi si possono avere numeri differenti di colonne cosa che rende il database una matrice multidimensionale, permettendo così di inserire attributi in più o in meno. Lo stesso si ha nel database a documenti, dove nulla vieta di creare un secondo documento che parla di un altro cliente dove non si hanno gli stessi attributi. Questo permette una grande flessibilità in quanto non si è confinati in uno schema, né se ne deve modificare uno. Nei database a colonna abbiamo due approcci fondamentali, il primo è quello descritto precedentemente. Poi abbiamo il super column family, che è un approccio più articolato. Questo permette di suddividere dati su diversi server, aggiungendo un’indicizzazione in più Qui si ha un primo livello da cui si accede a un secondo livello di chiavi che mi permette di accedere a una famiglia, si ragiona quindi per blocchi di attributi.
quindi scalo orizzontalmente separando le due tabelle, ma potrei prendere anche solo una porzione di una tabella.
- Il problema è ricostruire i dati con le query, se questa richiede di fare join con dati che si trovano in luoghi diversi, dovrei prima recuperarli e questa è un operazione molto costosa quando i dati sono tanti e distribuiti. C’è un teorema che teorizza una serie di proprietà dei sistemi distribuiti, il CAP theorem Questi tre aspetti non riescono ad essere soddisfatti tutti e tre insieme e questo comporta dei limiti a cui si cerca di sopperire. In particolare, le problematiche sono legate al tempo necessario per recuperare i dati à limite fisico non risolvibile = velocità di connessione tra persona che fa la query e il luogo dei dati (questa non può superare la velocità della luce). Quindi in base alla distanza noi sperimenteremo una latenza che è inevitabile. Questa latenza è alla base di alcuni problemi. In un sistema di tipo distribuito con diverse copie dello stesso dato su server differenti i dati potrebbero non essere sempre aggiornati. Il CAP theorem dice che un sistema distribuito non può garantire tutte e tre queste proprietà allo stesso tempo, cioè essere distribuito (partizionato), sempre disponibile (riuscire sempre a rispondere alle richieste di un utente), essere consistente (cioè dare risposte coerenti con i dati aggiornati). In altri termini, il CAP Theorem ci dice che Se vogliamo un sistema che sia
- highly available, ovvero in grado di lavorare con latenza minima
- costituito da centinaia o migliaia di nodi e che ciascun nodo
- sia tollerante alle interruzioni di rete ( messaggi persi, non recapitati, fallimento di processi, guasti hardware) Dobbiamo accettare che in alcuni momenti i dati non siano tutti sincronizzati, oppure di non avere la disponibilità di tutti i dati.
Esistono diverse forme di consistenza. I dB relazionali usano un concetto di consistenza forte, cioè i dati devono essere sempre coerenti, se il dato non è coerente non fa inserire il dato (es vincoli di integrità, foreign key). Questa consistenza forte nei sistemi non relazionali la perdiamo, abbiamo una consistenza debole o addirittura una Eventual consistency , ovvero a un certo punto sono sicuro che queste modifiche verranno riportate però in futuro, non so tra quanto. Accetto questo tipo di incertezza per avere una risposta più pronta. Quindi l’utente sa che quel dato potrebbe non essere l’ultimo inserito. Quindi cambiano le proprietà dei DBMS. I sistemi relazionali sono associati all’acronimo “ACID”: Atomicity, Consistency, Isolation Durability. Le operazioni che eseguiamo soddisfano queste 4 proprietà:
- Atomicity: dato un blocco di query da eseguire (transazione), non sono ammesse esecuzioni parziali
- Consistency: il DBMS rispetta i vincoli di integrità
- Isolation: ogni transazione deve essere isolata dalle altre (non interferiscono tra loro). Durante una transazione, le modifiche al database sono visibili solo all'utente che ha lanciato la transazione
- Durability: terminata una transazione, le modifiche sono visibili a tutti gli utenti Questo approccio viene superato dall’approccio non relazionale, con l’approcio BASE.
- Basically Available : il sistema risponde sempre alle richieste. La risposta tuttavia può essere anche negativa: “non sono in grado di fornire i dati”, o i dati forniti possono essere inconsistenti.
- Soft state : lo stato del sistema può cambiare nel tempo (anche in assenza di attività perché magari arriva la modifica bloccata per via della rete).
- Eventual consistency : a seguito dell’aggiornamento della replica di un dato, la modifica si propagherà a tutte le altre repliche e prima o poi il database assumerà uno stato consistente, in un futuro non definito. Memchached Cos'è Memcached?
- Un semplice sistema di caching in memoria.
Operazione CAS (Check and Set)
- Consente di aggiornare un valore solo se non è stato modificato da quando è stato letto.
- Si basa su un identificatore unico CAS (token):
- Usa gets per leggere un valore e ottenere il token CAS.
- Aggiorna il valore usando il comando cas fornendo il token. o Esempio : Sistema che si trova tutto nella RAM e quindi non permette di salvare dati su disco, il che significa che se spegniamo il computer perdiamo tutto, non c’è modo di salvare nulla. Per questo è solo a supporto di qualche applicazione. Non viene definito come un vero e proprio dbms ma piuttosto un sistema memcaching, ovvero per gestire dati temporanei a cui accedere in modo molto rapido. Tempi di accesso minimi. Possibilità di distribuire i dati. Abbandona la consistenza, non c’è nessun meccanismo per definire un approccio alla consistenza dei dati. L’unico meccanismo si rifà a una funzione che serve a verificare la correttezza dei dati, ma nessun meccanismo automatico. Le due operazioni saranno quella di add e quella di get per scrivere e recuperare informazioni. Particolarità: memorizza i dati per un certo tempo che può essere stabilito nel momento in cui si inserisce la chiave coppia-valore (es biglietto treno che può essere in carrello solo per tot tempo) à meccanismo di time-delivery. Va usato in applicazioni in cui si vuole scalare, avere grande velocità, quindi applicazioni web (dati sul login x esempio). Non adeguato per gestire i dati veri e propri di un applicazione. Costruito come un’applicazione sempre in ascolto sul server dove lo si istalla. Poi è in ascolto di istruzioni da utenti. Il suo server ha caratteristiche interessanti, i dati vengono tenuti in RAM quindi il limite di dati che può tenere è dato dallo spazio della RAM in quel momento à comporta quini che si memorizzino pochi dati (NON BIG DATA) => qui il problema è permettere a tanti utenti di memorizzare contemporaneamente pochi dati (si può settare un numero di utenti massimo che può utilizzarlo contemporaneamente). Operazioni: settare una coppia chiave-valore specificando il tempo in cui esisterà il get. La key deve essere una stringa ma può contenere qualsiasi tipo di carattere dentro à non si fa nessuna verifica quindi si fa la scrittura in RAM in un tempo brevissimo. Le chiavi possono essere 250 caratteri max. si può quindi istallare memcached su più computer per parallelizzare il suo lavoro e quindi distribuire gli utenti suddividendo il carico à non si hanno limiti sul numero massimo di computer da collegare. Posso usare altri computer anche per duplicare i dati (es carico di lavoro distribuito geograficamente o copie di sicurezza). Sintassi comandi: i tipi di informazioni che inseriamo quando eseguiamo un set non si limita a chiave e valore ma dobbiamo aggiungere una serie di parametri, dopo la chiave dobbiamo aggiungere un expiration time tempo in cui la chiave valore rimane in RAM espresso in secondi, se scrivo 0 non scade mai. Inoltre devo specificare le dimensioni del valore che sto per inserire (Es 2024 = 4(byte)).
Add si può usare solo se è la prima volta che inserisco la coppia chiave-valore. Set può essere un sostituto di add, per inserire una chiave ma anche per aggiornarla se già fosse presente. Replace aggiorna. Append permette di aggiungere caratteri senza andare a modificare tutto.
- L’utente 1 crea una variabile x con valore ciao.
- L’utente 2 vuole aggiungere un !, mentre l’utente 1 intende fare una modifica in un secondo momento.
- Per accorgersi se il valore è già stato modificato, Memcached associa alla variabile un token (numero di versione). Utilizzando l’operazione gets, è possibile ottenere il valore della variabile e il relativo token.
- Per modificare la variabile in modo sicuro, si usa l’operazione cas (compare-and- swap), dimostrando di conoscere il token corretto. In questo modo, è possibile aggiornare la variabile solo se il token non è cambiato, garantendo che nessun'altra modifica sia stata effettuata nel frattempo. Questo sistema evita aggiornamenti errati e mantiene la consistenza dei dati condivisi tra più utenti. Se inavvertitamente l’utente di partenza prova a fare una modifica ambiando il valore originale senza usare il token corretto il sistema non fa fare un inserimento allora a quel punto si riesegue una gets per vedere il valore corretto e poterlo quindi aggiornare correttamente. PYTHON import memcache # importare libreria
Inizializzazione della variabile client
mc = memcache.Client(['127.0.0.1:11211'],debug=0) # connessione con il server su cui è memecached
Esempio con stringa
mc.set('greet','Hello world') # usando queste funzoini non dobbiamo specificare il numero di byte come nel terminale x = mc.get('greet') # per leggere dato, recupero chiave e la metto nella variabile x print("Il contenuto di x è "+x)
Esempio con numero
mc.set('numero',30) mc.incr('numero') # incremento y = mc.get('numero') print("Il contenuto di y è "+str(y))
Esempio con dato strutturato (JSON) # inserisco come fosse un dizionario
di python coppie chiave valore mc.set_multi({'name':'Mario', 'surname':'Rossi', 'customer_num':'123456'}) z = mc.get('name') print("Il contenuto di z è "+z) w = mc.get_multi(['name','surname','customer_num']) # leggere contemporaneamente più dati à come dizionario print("Il contenuto di w è "+str(w)) print("Il valore dell'attributo 'name' di w è "+str(w['name'])) print("Lista degli attributi e dei valori di w:") for attribute in w.keys(): print("\t"+attribute+" - > "+str(w[attribute])) Esercizio Pensare a come può essere fatto un database su memcached di un carrello della spesa di un ipotetico e-commerce. Definire come sono fatte le ipotetiche chiavi, quante sono e che nomi hanno. Per progettare un database basato su Memcached per gestire un carrello della spesa di un e-commerce, è importante pensare a come organizzare i dati in modo efficiente, data la natura volatile e key-value di Memcached (che non ha persistenza integrata).
Struttura generale
Memcached memorizza i dati in formato key-value. Quindi, per ogni carrello della spesa, possiamo utilizzare una chiave unica che identifica l'utente o la sessione. I valori associati possono essere rappresentati come un oggetto JSON che contiene informazioni sul contenuto del carrello.
1. Definizione delle chiavi
Le chiavi in Memcached devono essere strutturate in modo tale da essere:
- Uniche per ogni utente o sessione.
- Chiare per il recupero dei dati in modo efficiente.
Ipotesi principali:
- Ogni utente o sessione ha un carrello.
- Ogni carrello può contenere più articoli.
- Potrebbero esserci metadati aggiuntivi, come la data di creazione del carrello o lo stato.
Chiavi proposte:
- Chiave per il carrello dell'utente:
- Nome della chiave: cart: o cart:
- Aggiornamento delle chiavi: quando un utente aggiunge o rimuove articoli dal carrello, è necessario aggiornare il valore della chiave cart: per riflettere il nuovo contenuto.
- Chiarezza dei nomi: è fondamentale che le chiavi seguano una convenzione di nomenclatura coerente per facilitare la gestione.
Schema delle chiavi:
- cart: → Contenuto del carrello.
- product: → Dettagli del prodotto.
- user: → Informazioni sull'utente.
Quante chiavi ci sono?
- Per ogni utente/sessione attiva: 1 chiave per il carrello (cart:).
- Per ogni prodotto presente nel catalogo: 1 chiave per prodotto (product:).
- Per gli utenti registrati, potrebbe esserci una chiave separata per le informazioni dell'utente: 1 chiave per utente (user:).
Esempio pratico:
Supponiamo che un utente con ID 12345 abbia 3 articoli nel carrello e ci siano 100 prodotti disponibili. Le chiavi potrebbero essere strutturate così:
- cart:12345 → Carrello dell'utente con ID 12345.
- product:1, product:2, product:3 → Dettagli dei prodotti nel carrello.
- user:12345 → Dettagli utente (opzionale). Questo approccio sfrutta la velocità di recupero di Memcached, garantendo che le operazioni sul carrello siano veloci ed efficienti. Immaginiamo di dover rappresentare i dati di un carrello. Dobbiamo dare un senso ai nostri dati proprio con la scelta delle chiavi, che nel nome dovranno contenere il significato. Proviamo a rappresentare il carrello di un utente. Ci interessa:
- Quantità per ciascun prodotto
- N. utenti nel sistema REDIS Redis è un database key-value in-memory , open source, che supporta la persistenza su disco. È spesso utilizzato come:
- Database per dati ad alta frequenza di accesso.
- Sistema di cache per migliorare le prestazioni delle applicazioni.
- Message broker per implementare sistemi di messaggistica in tempo reale. Caratteristiche Principali
- Key-Value Store : Valori associati a chiavi univoche, con possibilità di memorizzare dati complessi.
- Persistenza Opzionale : Memorizza i dati in RAM, ma può sincronizzarli su disco.
- Operazioni Atomic : Ogni operazione su una struttura dati è atomica.
Tipologie di Dati Supportati
- String (fino a 512 MB): Tipo di dato primitivo.
- Hashes : Coppie campo-valore, ideali per rappresentare oggetti.
- Lists : Liste ordinate di valori, utilizzabili come code FIFO o LIFO.
- Sets : Insiemi non ordinati con valori univoci, utili per test di appartenenza o operazioni insiemistiche.
- Sorted Sets : Insiemi ordinati con punteggi associati, adatti per classifiche o ranking. Casi d'Uso Tipici
- Gestione delle Sessioni Web : Dati legati a sessioni univoche e temporanee.
- Profili Utente : Informazioni rapide come preferenze e impostazioni.
- Carrelli della Spesa : Gestione di dati transitori per e-commerce.
- Classifiche in Tempo Reale : Ordinamento e punteggi dinamici grazie ai Sorted Sets.
- Cache di Dati Dinamici : Acceleration delle prestazioni per query frequenti. Operazioni Fondamentali Esempi di operazioni che Redis rende disponibili per i tipi di dato supportati: String
- set: Memorizza un valore.
- get: Recupera il valore associato a una chiave.
- del: Elimina una chiave.
- expire: Imposta una scadenza temporale. Hashes
- hset: Memorizza un campo-valore.
- hget: Recupera il valore associato a un campo.
- hdel: Rimuove un campo. Lists
- lpush/rpush: Inserisce valori a sinistra/destra della lista.
- lpop/rpop: Estrae valori da sinistra/destra. Sets
- sadd: Aggiunge un valore all'insieme.
- srem: Rimuove un valore.
- sunion: Esegue l'unione di due o più insiemi. Sorted Sets
- zadd: Aggiunge un valore con punteggio.
- zrange: Recupera i valori in un intervallo ordinato.
set à specifichiamo la coppia, sia il value che il key, serve per inserire la coppia, e posso se voglio dare un expiration time (ex con numero di secondi, elimina la coppia passati quei secondi) se non lo specifico la coppia non scade mai. Anche la funzione di append è la stessa. Esistono però comandi specifici di redis Exist à per sapere se la chiave esiste in questo particolare momento (true o fasle) Del à elimina la coppia Setse à inserisci se non esiste già la coppia (meccanismo di protezione per non alterare una coppia già esistente) Altri comandi: expirekey + num secondi à settare un time-out per una chiave (assegnare o ridefinire il tempo di scadenza) ttl à quanti sec rimangono a quella chiave persist à azzera contatore per una certa chiave (la posso rendere permanente) Esempi comandi
- 2 è un codice interno per dire che la variabile non esiste Nel caso degli hash il value è fatto di tante coppie chiave-valore e quindi devo inserirli separatamente con: hset à variante del set in cui specifico chiave, field e valore. Per inserire dati studenti questa chiave la inserirò più volte Anche in fase id lettura il discorso è simile perché dovrò specificare sia la chiave che il valore che voglio andare a leggere. Ogni tipo di dato è una variante del comando con una lettera davanti che indica il tipo di dato: es hexists à esiste una chiave con quel nome e campo li? 1 = true (esiste) hdel à cancella il singolo field hcase à indicando la chiave ho la lista dei field che ho dentro (non c’è in memecached) hvals à posso estrarre tutti i valori di quei field questo è quello che possiamo fare con gli hash à raggruppare tutto in un oggetto in pratica, ci avviciniamo un po’ a quello che è la tabella (nel value metto le righe della tabella) il set è una struttura semplice che permette di inserire valori senza un ordine, quidni verrranno memorizzati senza ordine. Per aggiungere elemento abbiamo sadd dove inserisco la key e specifico il value Srem à elimino il value da quella chiave Cardinalità dice quanti elementi ci sono all’interno Members à elenca gli elementi dell’insieme Pop à estraiamo un elemento per visualizzarlo ma lo eliminiamo pure, come se fosse un elemento processato. Esempio 1: Elenco di Città
- Memorizzare un elenco di città utilizzando un Set.
- I dati vengono inseriti tramite il comando sadd.
- Visualizzare tutti gli elementi con smembers, ricordando che i Set non preservano l’ordine di inserimento.
- Verificare la cardinalità del Set (numero di città) con scard.
Comandi Redis: Esempio 2: Confronto Hobby di Elisa e Marco
- Obiettivo : Analizzare e confrontare gli hobby di due persone.
- Intersezione : Identificare hobby comuni con sinter.
- Unione : Trovare l’elenco completo degli hobby con sunion.
- Differenza : Scoprire gli hobby di una persona che l’altra non condivide con sdiff. Comandi Redis: Applicazione Avanzata: Similarità tra Clienti
- Scenario : Determinare quanto sono simili due clienti basandosi sugli articoli acquistati.
- Unione : Mostra l’elenco complessivo di articoli acquistati.
- Intersezione : Identifica gli articoli acquistati da entrambi i clienti.
- Questo approccio può essere usato per supportare un Recommendation System : o Suggerire articoli non acquistati ma simili a quelli di altri clienti. Comandi Redis: Un evoluzione del set è il sorting set, dove non posso duplicare i dati all’interno della struttura, posso duplicare solo il valore che mi serve per ordinare. Tutti questi comandi sono anticipati da una lettera z perché è un tipo di istruzione che funziona solo sui sorting set, e posso usare add ma la differenza è che devo aggiungere lo score. Es lista film di un regista, chiave = regista, come score = data uscita. In questo caso posso calcolare la cardinalità.