2010-08-14 7 views
5

Domanda: Quando si dispone di un GUID .NET per l'inserimento in una banca dati, la sua struttura è simile a questo:Localmente identificatore unico

60 bits of timestamp, 
48 bits of computer identifier, 
14 bits of uniquifier, and 
6 bits are fixed, 
---- 
128 bits total 

Ora ho un problema con un GUID, perché è un numero a 128 bit, e alcuni dei DB che sto utilizzando supportano solo numeri a 64 bit.

Ora non voglio risolvere il dilemma utilizzando un valore bigint autoincrement, poiché voglio essere in grado di eseguire la replica offline.

Così ho avuto l'idea di creare una classe identificatore univoca localmente, che è fondamentalmente un GUID ridimensionato a un valore a 64 bit.

sono arrivato fino a questo:

day 9 bit (12*31=372 d) 
year 8 bit (2266-2010 = 256 y) 
seconds 17 bit (24*60*60=86400 s) 
hostname 12 bit (2^12=4096) 
random 18 bit (2^18=262144) 
------------------------ 
      64 bits total 

La mia domanda ora è: Il timestamp è praticamente fissato a 34 bit, lasciandomi con 64-34 = 30 bit per il numero casuale hostname +.

Ora la mia domanda: 1) Preferiresti aumentare il bit di hash dell'hostname e diminuire il bitsize casuale, o aumentare il bitsize casuale e diminuire il bit di hash dell'hostname.

2) Esiste un algoritmo hash che riduce ogni stringa in n bit? n idealmente = 12 o il più vicino possibile.

risposta

3

In realtà, i GUID generati da .NET sono 6 bit fissi e 122 bit di casualità.

Si potrebbe prendere in considerazione solo l'uso di 64 bit di casualità, con una maggiore probabilità di collisione a causa della minore lunghezza del bit. Funzionerebbe meglio di un hash.

+0

Ci sono vari approcci; Mi piace anche l'idea di un "id del nodo" con un timestamp (nessuna casualità). È possibile creare facilmente un ID nodo con qualsiasi numero di bit eseguendo XOR un hash crittografico (ad es. SHA1). Meno bit, più alta è la probabilità di una collisione di id di nodo, ovviamente. L'"unificatore" che hai menzionato è in realtà utilizzato da altri algoritmi di Guid per gestire gli orologi di sistema andando all'indietro, per mantenere i timestamp univoci per id di nodo. Ma alla fine della giornata, ti verrà difficile trovare una soluzione che garantisca meno collisioni rispetto alla pura casualità. Ricordate, questo è tutto .NET Guids ... –

+0

Mentre la probabilità di 1/2^64 è ancora un numero molto piccolo, non mi piace il pensiero di un numero casuale puro. Ma ho pensato di omettere completamente l'hash dell'hostname e di aumentare il numero casuale a 30 bit. Ma questa non è una buona idea, perché per n client offline, ciò renderebbe la possibilità di collisione andare a 2^30 * n. Per 100 clienti, questo è solo circa uno su 10 milioni. Con molta sfortuna, si potrebbe semplicemente colpire il jackpot lì ... –

+0

1/2^64 == 1 su 18 sett. (Un settilione == un trilione un trilione, o un milione di milioni di milioni). Se vai in modo completamente casuale ... –

2

Se lo spazio non è un problema, allora perché non si usano solo 2 colonne larghe 64 bit, quindi si divide il guid a metà usando 8 byte per ciascuno, quindi si convertono solo i numeri a 64 bit e lo si memorizza in 2 colonne, quindi se hai mai bisogno di eseguire l'upsize su un altro sistema, rimarrai comunque univoco, dovrai solo prendere in considerazione il ricongiungimento delle 2 colonne.

+0

Quindi dovrò confrontare due numeri per ogni join. Non diminuisce le prestazioni di troppo? –

+0

Bene coinvolgerete una colonna in più nella vostra chiave [im assumendo che la guid sia una chiave] in modo da avere un leggero cambiamento, ma in questo modo non perdete il Guid sui sistemi che possono supportarlo e avete una soluzione per quelli che non lo fanno. –

0

Perché scrivere il tuo? Perché non generare un numero uniformemente casuale? Farà il lavoro bene. Basta prendere le prime X cifre in cui X è la dimensione desiderata ... diciamo 64-bit.

Vedere here per informazioni su RAND() rispetto a NEWID() in SQL Server, che è in realtà solo un'accusa di GUID contro generatori di numeri casuali. Inoltre, vedi here se hai bisogno di qualcosa di più casuale di System.Random.

+0

I numeri completamente casuali non sono una buona idea, IMHO. Non voglio preoccuparmi dei duplicati e degli errori strani quando il database diventa sempre più grande. Almeno un timestamp deve essere integrato in qualche modo. Anche se ci pensiamo, potrebbe essere più saggio lasciare i secondi e aumentare semplicemente la dimensione dei numeri casuali. In questo modo posso avere un hash hostname abbastanza lungo e un numero casuale abbastanza lungo. –