Funzione hash priva di collisioni per l'utilizzo in tabelle hash e altre strutture dati?

0

Una breve introduzione al problema: sto lavorando con un piccolo database in cui ho una tabella di stringhe (URL web, per essere precisi) come coppie: hash|string . Un'altra tabella fa riferimento a queste stringhe per hash, quindi sto risparmiando molto spazio e alcuni cicli della CPU usando gli hash (un identificativo compatto di una stringa). Sapevo che le collisioni sarebbero state un problema con insiemi di dati di grandi dimensioni, ma non mi aspettavo di iniziare a battere collisioni non appena avevo 281 000 stringhe univoche per un hash a 64 bit.

Quindi, ho bisogno di una funzione simile a un hash che non deve essere crittografica e non ha nemmeno bisogno di essere distribuita uniformemente. Potrebbe essere di lunghezza variabile, ma vorrei prima spremere il più possibile da 64 bit di entropia.

Idea n. 1: usa il numero di posizione di una stringa nella tabella come ID univoco. Funzionerebbe, ma non mi piace come si basa su un singolo contatore globale per l'assegnazione di un numero incrementato. Se non altro, è un punto di congestione per un sistema distribuito con più scrittori e lettori.

Idea n. 2: comprime le stringhe. Ma come? Apparentemente, dovrebbe essere un algoritmo di compressione con un dizionario pre-calcolato. Anche allora, quanti personaggi, in media, sarebbe possibile schiacciare a 64 bit?

Idea n. 2.5: comprimibile se comprimibile per il numero di bit di destinazione, altrimenti hash.

Si noti che con "hash-like" intendo che la funzione non deve essere reversibile.

    
posta Violet Giraffe 12.10.2018 - 18:32
fonte

1 risposta

4

Scrivi "Idea # 1: usa il numero di posizione di una stringa nella tabella come ID univoco." ma non è così che funzionano le sequenze. Se si desidera evitare la contesa intorno alle sequenze, si utilizzano i batch di sequenza. Quello è che ogni scrittore prende, diciamo, una gamma di 1000 sequenze da usare. Ho pensato che fosse integrato in almeno alcuni database / driver, ma è possibile implementarlo utilizzando le funzionalità di base delle sequenze. Basta impostare il valore dell'incremento su N ( N è qualunque sia la dimensione del batch) e chiedere allo scrittore di recuperare il primo. Quindi può incrementare il valore internamente fino a quando non hai creato N voci. Quindi richiedi un altro. Sei sicuro di non avere collisioni e sarà più veloce e utilizzare meno spazio di un hash.

Se vuoi veramente evitare un generatore di sequenze nel DB, puoi avere un generatore di identità basato sull'identità dello scrittore e fare in modo che ogni scrittore gestisca la propria sequenza. UUID versione 1 & 2 usare questa idea di base. Si potrebbe assegnare a ogni scrittore un intero 'nome' o utilizzare qualsiasi altro approccio in cui abbiano identificatori univoci. Impedisci questo all'ID e sai che non entreranno in collisione con i valori creati da altri autori.

    
risposta data 12.10.2018 - 19:03
fonte

Leggi altre domande sui tag