Scelta dell'algoritmo giusto nella funzione HashBytes


20

Dobbiamo creare il valore hash dei dati nvarchar a fini di confronto. Ci sono più algoritmi di hash disponibili in T-SQL, ma quale è il migliore tra cui scegliere in questo scenario?

Vogliamo garantire il rischio di avere un valore hash duplicato per due diversi valori nvarchar è il minimo. Sulla base delle mie ricerche su Internet, MD5 sembra il migliore. È giusto? MSDN ci dice (link sotto) degli algoritmi disponibili, ma nessuna descrizione su quale per quali condizioni?

HASHBYTES (Transact-SQL)

Dobbiamo unire due tabelle su due colonne nvarchar (max). Come puoi immaginare, l'esecuzione della query richiede molto tempo. Abbiamo pensato che sarebbe meglio mantenere il valore di hash di ciascun dato nvarchar (max) e fare l'unione sui valori di hash piuttosto che sui valori di nvarchar (max) che sono BLOB. La domanda è quale algoritmo di hash fornisce l'unicità, in modo da non correre il rischio di avere un valore di hash per più di un nvarchar (max).

Risposte:


18

La HASHBYTESfunzione richiede solo fino a 8000 byte come input. Poiché i tuoi input sono potenzialmente più grandi di così, i duplicati nell'intervallo del campo che viene sottoposto a hash causeranno collisioni, indipendentemente dall'algoritmo scelto. Valuta attentamente l'intervallo di dati che prevedi di eseguire l'hash: utilizzare i primi 4000 caratteri è la scelta ovvia , ma potrebbe non essere la scelta migliore per i tuoi dati.

In ogni caso, a causa di ciò che è una funzione hash, anche se gli input sono 8000 byte o meno, l' unico modo per garantire la correttezza del 100% nei risultati è confrontare i valori di base ad un certo punto (leggi: non necessariamente prima ). Periodo.

L'azienda stabilirà se è richiesta o meno la precisione al 100%. Questo ti dirà che (a) è necessario confrontare i valori di base , oppure (b) dovresti considerare di non confrontare i valori di base - quanta precisione dovrebbe essere scambiata per le prestazioni.

Sebbene le collisioni di hash siano possibili in un unico set di input, sono infinitamente rare, indipendentemente dall'algoritmo scelto. L'idea generale di utilizzare un valore di hash in questo scenario è restringere in modo efficiente i risultati del join a un set più gestibile, non necessariamente per arrivare immediatamente al set finale di risultati. Ancora una volta, per una precisione del 100%, questo non può essere il passaggio finale del processo. Questo scenario non utilizza l'hashing ai fini della crittografia, quindi un algoritmo come MD5 funzionerà correttamente.

Sarebbe estremamente difficile per me giustificare il passaggio a un algoritmo SHA-x per scopi di "accuratezza" perché se il business impazzirà per le minuscole possibilità di collisione di MD5, è probabile che stiano anche impazzendo che neanche gli algoritmi SHA-x sono perfetti. O devono fare i conti con la leggera inesattezza, o imporre che la query sia accurata al 100% e conforme alle implicazioni tecniche associate. Suppongo che se il CEO dorme meglio la notte sapendo che hai usato SHA-x invece di MD5, bene, va bene; in questo caso non significa ancora molto dal punto di vista tecnico.

A proposito di prestazioni, se le tabelle sono per lo più lette e il risultato del join è necessario frequentemente, prendere in considerazione l'implementazione di una vista indicizzata per eliminare la necessità di calcolare l'intero join ogni volta che viene richiesto. Ovviamente, si risparmia spazio per quello, ma può valerne la pena per il miglioramento delle prestazioni, in particolare se è richiesta una precisione del 100%.

Per ulteriori informazioni sull'indicizzazione di valori di stringhe lunghe, ho pubblicato un articolo che illustra un esempio di come eseguire questa operazione per una singola tabella e presenta aspetti da considerare quando si tenta lo scenario completo in questa domanda.


8

MD5 dovrebbe andare bene e l'output può essere archiviato in un file binario (16). La probabilità di una collisione (vedi paradosso del compleanno ) è ancora molto bassa, anche con una grande dimensione del campione fisico. L'output di SHA-1 richiede 20 byte e l'output di SHA-256 richiede 32 byte. A meno che tu non abbia un numero così elevato di record che la probabilità di collisione del tuo compleanno diventa significativa (fisicamente impossibile o almeno impraticabile con le attuali tecnologie hardware) probabilmente sarà OK.



0

Non ho visto questo menzionato nelle risposte ma per MSDN :

A partire da SQL Server 2016 (13.x), tutti gli algoritmi diversi da SHA2_256 e SHA2_512 sono obsoleti. Gli algoritmi precedenti (non consigliati) continueranno a funzionare, ma genereranno un evento di deprecazione.

Ho fatto una domanda simile, quindi spetta a te se desideri utilizzare una funzione obsoleta come MD5 (se sei su 2016+). È possibile eseguire i test per vedere quanta differenza c'è nello storage e nelle prestazioni tra MD5 e SHA2.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.