Dove trovo nel libro il capitolo che mi in­te­res­sa­va tanto? Dove va a finire l’ordine di Maria Rossi? Dove è possibile ac­qui­sta­re l’orologio con il cinturino in pelle marrone? – Cosa hanno in comune queste tre domande? Questi quesiti ri­guar­da­no luoghi (“Dove?”) e tutti e tre pre­sup­pon­go­no che ciò che si cerca esista. Questo modello di idea può essere fa­cil­men­te tra­sfe­ri­to nel mondo delle banche dati.

Im­ma­gi­na­te un negozio online con migliaia di articoli e clienti. Tutti questi dati sono me­mo­riz­za­ti in database. Il cliente ricerca nel database un articolo specifico ed effettua un ordine, mentre il mittente assegna l’articolo ordinato, tramite il database, all’ac­qui­ren­te con i propri dati di indirizzo. Ciò si traduce in varie attività di ricerca e or­di­na­men­to, oltre a processi di in­se­ri­men­to ed eli­mi­na­zio­ne durante il processo di or­di­na­zio­ne. Per gestire questo tipo di compiti nel modo più ef­fi­cien­te, grandi quantità di dati affini sono combinati in una posizione di indirizzo nel database. Questa posizione viene calcolata con valori hash ed è co­sti­tui­ta da una tabella di com­bi­na­zio­ni al­fa­nu­me­ri­che­che hanno sempre la stessa lunghezza. Il nostro articolo vi il­lu­stre­rà i principi di utilizzo di queste tabelle hash.

Qual è il principio di una tabella hash?

In­nan­zi­tut­to, un valore hash è calcolato in base alle in­for­ma­zio­ni di un set di dati. I valori hash di tutti i set di dati di un database sono inseriti in una tabella hash. A partire dal valore hash, un’ulteriore ope­ra­zio­ne ma­te­ma­ti­ca calcola la posizione di me­mo­riz­za­zio­ne di queste in­for­ma­zio­ni nel database. Se l’utente immette ora un termine di ricerca, viene eseguito anche l’hash. A questo punto, la ricerca non viene più eseguita per “orologio da polso con cinturino in pelle marrone”, ma per una cor­ri­spon­den­za tra il valore hash ori­gi­na­rio dell’articolo e il valore hash del termine di ricerca appena uti­liz­za­to. In altre parole, viene ricercata una cor­ri­spon­den­za tra due com­bi­na­zio­ni al­fa­nu­me­ri­che. È un metodo che viene uti­liz­za­to per le soluzioni più disparate.

Pro­te­zio­ne e valori hash

Con l’as­se­gna­zio­ne di hash generati au­to­ma­ti­ca­men­te a termini arbitrari viene creata una tabella hash. La funzione hash uti­liz­za­ta a questo scopo genera un hash, ovvero una stringa di caratteri che è sempre della stessa lunghezza. La lunghezza della stringa e i caratteri in essa contenuti sono de­ter­mi­na­ti dal metodo di hashing uti­liz­za­to. L’hashing viene uti­liz­za­to, ad esempio, per rendere i dati di accesso più sicuri contro gli attacchi.

Quando si tenta di ef­fet­tua­re il login nell’esempio del database di WordPress, la password inserita dall’utente viene con­ver­ti­ta in un valore hash uti­liz­zan­do la stessa procedura, per poi essere con­fron­ta­to con la voce nel campo “user_pass” del database. Se i due hash di 34 caratteri cor­ri­spon­do­no, l’accesso è con­sen­ti­to. Ri­con­ver­ti­re un valore hash nella password cor­ri­spon­den­te non è possibile. Questa ca­rat­te­ri­sti­ca evidenzia l’utilità di una funzione hash.

In caso di tentativi di accesso non au­to­riz­za­to, come gli attacchi brute force, l’ag­gres­so­re dovrebbe provare tutte le com­bi­na­zio­ni possibili di caratteri fino a trovare una cor­ri­spon­den­za con questa stringa. Se la funzione hash uti­liz­za­ta è nota e si uti­liz­za­no lettere maiuscole, lettere minuscole e cifre in una password di 10 caratteri, un cy­ber­cri­mi­na­le dovrebbe ef­fet­tua­re esat­ta­men­te 839.299.365.868.340.200 tentativi per trovare una cor­ri­spon­den­za.

Uso più rapido delle banche dati

Nei database, le tabelle hash vengono uti­liz­za­te per ac­ce­le­ra­re le ricerche e l’im­mis­sio­ne o l’eli­mi­na­zio­ne di set di dati. Prendiamo come esempio la ricerca di un cognome nel database dei di­pen­den­ti di una società. Una ricerca di questo tipo può ri­chie­de­re molto tempo dal momento che la cor­ri­spon­den­za viene ricercata in sequenza in ogni campo del database. Se il termine di ricerca viene con­ver­ti­to in un valore hash e si cerca una cor­ri­spon­den­za nella tabella hash, in genere si ottiene il risultato molto più ra­pi­da­men­te.

Ma come funziona? A ogni set di dati viene assegnato un indirizzo univoco. All’interno del database, questo tipo di in­di­riz­za­men­to è sempre identico (001, 002, 003 o 00A1, 00A2, 00A3, ecc.). Questo indirizzo viene calcolato mediante la funzione hash.

Guardiamo un semplice esempio: un database ha spazio per 11 voci, dalla posizione 0 alla posizione 10. Il nome “Lisa” è composto da quattro caratteri ASCII con i ri­spet­ti­vi codici ASCII: L è 76, i è 105, s è 115 e a è 97. Provatelo voi stessi in Windows con il ta­stie­ri­no numerico: [Alt] + 0076, ad esempio, re­sti­tui­sce “L”. Tutti i valori ASCII vengono sommati e per “Lisa” otteniamo come risultato il valore hash 393. La somma dei valori ASCII cor­ri­spon­de ora a una funzione hash.

A questo punto viene eseguito un calcolo del valore residuo con numeri interi: 393 % 11 (posizioni di memoria) = 35, con resto di 8 (il segno per­cen­tua­le “%” cor­ri­spon­de all’operatore ma­te­ma­ti­co per il calcolo del valore residuo in molti linguaggi di pro­gram­ma­zio­ne). Questo valore residuo determina a quale punto del database, in questo caso il numero di indice 8, vengono me­mo­riz­za­te Lisa e tutte le altre in­for­ma­zio­ni a lei legate. È facile im­ma­gi­na­re che in questo tipo di in­di­riz­za­men­to emergano fre­quen­te­men­te valori residui identici. Tuttavia, maggiori sono il numero di posizioni di memoria e la lunghezza del valore hash uti­liz­za­to, minore è la pro­ba­bi­li­tà che si verifichi una du­pli­ca­zio­ne. Con­si­de­ria­mo, ad esempio, il nome “Alis Meyer” che, no­no­stan­te utilizzi le “stesse” lettere, re­sti­tui­reb­be un po­si­zio­na­men­to com­ple­ta­men­te diverso, poiché la “A” è diventata maiuscola e la “l” minuscola.

La figura mostra il problema della du­pli­ca­zio­ne: nomi diversi rimandano a indici identici, creando le co­sid­det­te col­li­sio­ni (frecce azzurre). Cosa “fa” il database quando si verifica un “incidente” del genere? Il set di dati doppio viene me­mo­riz­za­to nel primo posto vacante di­spo­ni­bi­le nel database. Se nell’esempio ef­fet­tuia­mo una ricerca per “Berta Müller”, il puntatore inizia la ricerca non dalla posizione 001, ma piuttosto dalla posizione di indice 003, che permette di ottenere un (leggero) risparmio di tempo. Questo metodo viene definito hash con in­di­riz­za­men­to aperto, in cui viene quindi eseguita un’ispezione lineare.

Il fun­zio­na­men­to degli hash con con­ca­te­na­zio­ne è leg­ger­men­te diverso. Invece di “aprire” un nuovo set di dati, quello suc­ces­si­vo alla prima voce cor­ri­spon­den­te viene me­mo­riz­za­to in modo con­ca­te­na­to. Pertanto, è possibile in­di­vi­dua­re con una sola ricerca il set di dati cercato: iden­ti­fi­can­do il primo set di dati si trova anche l’altro cor­ri­spon­den­te a quella posizione di me­mo­riz­za­zio­ne. Ciò si traduce in un aumento della velocità di ela­bo­ra­zio­ne.

Nella ricerca per “Berta Müller”, il puntatore parte subito dal valore 003 calcolato dalla tabella hash e deve, da qui, ricercare solo un set di dati con­ca­te­na­to. Questo consente di “im­pac­chet­ta­re” grandi quantità di dati in modo più elegante e di ri­cer­car­li più ra­pi­da­men­te.

Questo principio viene uti­liz­za­to anche nel co­sid­det­to “caching” al fine di poter accedere ra­pi­da­men­te a dati già uti­liz­za­ti. Questi dati vengono me­mo­riz­za­ti nella cache e re­cu­pe­ra­ti da lì se richiesti. Questo accade, ad esempio, con i siti web visitati che, invece di essere ri­ca­ri­ca­ti da zero dal server quando li visitiamo per la seconda volta, vengono re­cu­pe­ra­ti dalla cache ri­spar­mian­do molto tempo. Anche i cookie svolgono una sorta di iden­ti­fi­ca­zio­ne com­pa­ra­ti­va, per ri­co­no­sce­re i “luoghi” già visitati dall’utente sul web.

Metodi di hashing

Il metodo di hashing appena descritto viene anche definito hashing aperto o in­di­riz­za­men­to chiuso, in cui i dati possono essere me­mo­riz­za­ti in liste con­ca­te­na­te in uno spazio di memoria teo­ri­ca­men­te il­li­mi­ta­to. Sebbene il numero di chiavi di­spo­ni­bi­li non sia maggiore, la con­ca­te­na­zio­ne consente di gestire quantità maggiori di dati. In questo caso, la parola “aperto” fa ri­fe­ri­men­to alla libertà di usare una lista separata dalla tabella hash.

Quando l’hashing è chiuso, il numero di chiavi di­spo­ni­bi­li è limitato dalla capacità della tabella. Se si tenta di me­mo­riz­za­re più dati, viene creato un co­sid­det­to “overflow”. A una nuova ese­cu­zio­ne della tabella, si in­di­vi­dua­no le posizioni ancora libere in cui è possibile po­si­zio­na­re questi “overflow”.

N.B.

L’uso dei termini hashing “aperto” e “chiuso” non è chia­ra­men­te regolato e possono essere uti­liz­za­ti in modo equivoco nelle pub­bli­ca­zio­ni. Si rac­co­man­da di uti­liz­za­re la ri­spet­ti­va de­scri­zio­ne det­ta­glia­ta del metodo.

L’hashing cuckoo è un altro metodo per evitare col­li­sio­ni nella tabella del database. Il termine deriva dal com­por­ta­men­to del cuculo di rimuovere le uova dai nidi di altri uccelli per poi de­po­si­tar­vi le proprie. Ad esempio, vengono uti­liz­za­te due funzioni hash per definire due posizioni di me­mo­riz­za­zio­ne. Se la prima posizione è già occupata, la chiave già presente viene spostata in una nuova posizione, mentre la seconda chiave generata viene po­si­zio­na­ta nella prima posizione di me­mo­riz­za­zio­ne. Lo svan­tag­gio di questa variante è che può formarsi un ciclo di ricerca infinito, tanto da terminare una routine a causa del timeout.

Per ef­fet­tua­re una ricerca nel database, ci sono vari metodi costruiti con com­pli­ca­te formule ma­te­ma­ti­che che si na­scon­do­no su un sito web sotto forma di codice di pro­gram­ma­zio­ne, per esempio dietro il semplice campo di ricerca con la lente di in­gran­di­men­to.

I database tendono ad in­gran­dir­si e il volume dei dati cresce a dismisura. L’hashing dinamico tiene conto di questo, in­gran­den­do la tabella hash per evitare col­li­sio­ni. Ciò comporta tuttavia anche la modifica dei valori hash dei dati già me­mo­riz­za­ti. Sono state svi­lup­pa­te speciali funzioni hash che risolvono ele­gan­te­men­te anche questo problema. Pertanto, non esiste (almeno teo­ri­ca­men­te) alcun limite per la quantità di dati. Tuttavia, con l’aumento del volume di dati le ricerche diventano meno ef­fi­cien­ti.

Vantaggi e svantaggi delle tabelle hash

Il vantaggio maggiore dell’utilizzo di una tabella hash è che permette di ef­fet­tua­re ra­pi­da­men­te ricerche in una grande quantità di dati. Il fatto che gli ar­chi­tet­ti di database siano costretti a stimare le di­men­sio­ni richieste con largo anticipo al fine di mantenere basso il rischio di col­li­sio­ne rap­pre­sen­ta un aspetto meno pratico. È possibile uti­liz­za­re molti tipi di dati purché per­met­ta­no di calcolare i valori hash.

Tra i punti deboli di questo approccio si annovera il fatto che un gran numero di col­li­sio­ni può far de­ge­ne­ra­re le banche dati. La pro­ba­bi­li­tà di col­li­sio­ni aumenta con la quantità di dati. Diverse funzioni hash non con­sen­to­no, inoltre, di passare al set di dati suc­ces­si­vo o pre­ce­den­te.

Vai al menu prin­ci­pa­le