2014-05-20 11 views
8

Ho un'applicazione per gestire un file e frammentarlo su più segmenti, quindi salvare il risultato in SQL Server Banca dati. Esistono molti file duplicati (magari con percorso file diverso), quindi prima di tutto analizzo tutti questi file e computo l'hash Md5 per ogni file e contrassegno il file duplicato utilizzando la colonna [Duplicato].Vantaggi e svantaggi dell'utilizzo di MD5 Hash come chiave primaria rispetto all'utilizzo di un'identità int come chiave primaria in SQL Server

Poi ogni giorno eseguirò questa applicazione e salverò i risultati nella tabella [Risultato]. Lo schema db è come qui sotto:

CREATE TABLE [dbo].[FilePath] 
    (
     [FilePath] NVARCHAR(256) NOT NULL PRIMARY KEY, 
     [FileMd5Hash] binay(16) NOT NULL, 
     [Duplicated] BIT NOT NULL DEFAULT 0, 
     [LastRunBuild] NVARCHAR(30) NOT NULL DEFAULT 0 
    ) 

    CREATE TABLE [dbo].[Result] 
    (
     [Build] NVARCHAR(30) NOT NULL, 
     [FileMd5Hash] binay(16) NOT NULL , 
     [SegmentId] INT NOT NULL, 
     [SegmentContent] text NOT NULL 
     PRIMARY KEY ([FileMd5Hash], [Build], [SegmentId]) 
    ) 

E ho un obbligo di aderire a questi 2 tabella a FileMd5Hash.

Dal momento che il numero di righe di [Risultato] è molto grande, vorrei aggiungere una colonna int Identity per unire queste tabelle come qui sotto:

CREATE TABLE [dbo].[FilePath] 
    (
     [FilePath] NVARCHAR(256) NOT NULL PRIMARY KEY, 
     [FileMd5Hash] binay(16) NOT NULL, 
     **[Id] INT NOT NULL IDENTITY,** 
     [Duplicated] BIT NOT NULL DEFAULT 0, 
     [LastRunBuild] NVARCHAR(30) NOT NULL DEFAULT 0 
    ) 

    CREATE TABLE [dbo].[Result] 
    (
     [Build] NVARCHAR(30) NOT NULL, 
     **[Id] INT NOT NULL,** 
     [SegmentId] INT NOT NULL, 
     [SegmentContent] text NOT NULL 
     PRIMARY KEY ([FileMd5Hash], [Build], [SegmentId]) 
    ) 

Quindi qual è la Pro e contro di questi 2 modi?

+2

Si noti che l'algoritmo MD5 può produrre valori duplicati per dati completamente diversi.Controlla wikipedia, ha più dettagli. Penso che l'uso di 'int' id sia migliore, in quanto verrà indicizzato in modo più efficiente. – cha

+0

Non ci sono abbastanza informazioni qui per capire cosa stai cercando di fare e perché potresti aver bisogno di una colonna di identità. – usr

risposta

8

Un tasto int è più semplice da implementare e più facile da usare e da capire. È anche più piccolo (4 byte contro 16 byte), quindi gli indici si adattano al doppio del numero di voci per pagina IO, il che significa prestazioni migliori. Anche le righe della tabella saranno più piccole (OK, non molto più piccole), quindi di nuovo avrai più righe per pagina = meno IO.

Hash può sempre provocare collisioni. Sebbene estremamente raro, tuttavia, come mostra lo birthday problem, le collisioni diventano sempre più probabili man mano che aumenta il conteggio dei record. Il numero di elementi necessari per un 50% di probabilità di una collisione con varie hash bit di lunghezza è la seguente:

Hash length (bits) Item count for 50% chance of collision 
       32 77000 
       64 5.1 billion 
       128 22 billion billion 
       256 400 billion billion billion billion 

C'è anche il problema di dover passare intorno byte non ASCII - più difficile da mettere a punto, inviare oltre filo, ecc.

Utilizzare le chiavi primarie sequenziali per le vostre tabelle int. Lo fa chiunque altro.

+0

+1 solo per l'ultima frase -) – trailmax

+0

[Calcolo verificato] (http://www.wolframalpha.com/input/?i=1+-++%28+1+%2F+%282%5E32%29+ % 29% 5E70000 * +% 28 +% 28 +% 282% 5E32% 29% 21 +% 29 +% 2F +% 28 +% 28% 282% 5E32% 29 + - + 70000% 29 +% 21 +% 29 + % 29). Probabilità ~ 0.44 con 32 bit e 70.000 elementi. Con 140.000, è quasi il 90%. Ciò significa che è praticamente inutile per quell'ordine di articoli se l'unicità è fondamentale. – Medorator

+0

@usr di cosa stai parlando? Sto dicendo di usare una chiave sequenziale 'int' (surrogata) e * non * per usare gli hash come chiavi. Questa è una questione pratica non correlata alla crittografia o alla sicurezza. – Bohemian

0

Utilizzare le inte per le chiavi primarie, non gli hash. Tutti mettono in guardia contro le collisioni di hash, ma in pratica non sono un grosso problema; è facile verificare la presenza di collisioni e re-hash. Gli ID sequenziali possono collidere anche se si uniscono i database.

Il grosso problema con gli hash come chiavi è che non è possibile modificare i dati. Se ci provi, il tuo hash cambierà e tutte le chiavi esterne non saranno più valide. Devi creare una colonna "no, questo è il vero hash" nel tuo database e il tuo vecchio hash diventa un grande numero intero non sequenziale.

Scommetto che il vostro analista di business dirà "implementiamo WORM in modo che i nostri record non cambieranno mai". Saranno smentiti.

Problemi correlati