2009-02-26 23 views
8

Voglio calcolare un checksum di tutti i valori di una colonna in modo aggregato.Creare un checksum aggregato di una colonna

In altre parole, voglio fare un po 'equivalente di

md5(group_concat(some_column)) 

Il problema di questo approccio è:

  1. E' inefficiente. Deve concatenere tutti i valori della colonna come stringa in una memoria temporanea prima di passarla alla funzione md5
  2. group_concat ha una lunghezza massima di 1024, dopodiché tutto il resto verrà troncato.

(Nel caso in cui vi state chiedendo, è possibile garantire che il concat dei valori è in un ordine coerente, tuttavia, come ci crediate o no group_concat() accetta un ordine dalla clausola al suo interno, ad esempio group_concat(some_column order by some_column))

MySQL offre le funzioni di aggregazione bit per bit non standard BIT_AND(), BIT_OR() e BIT_XOR() che presumo sarebbe utile per questo problema. La colonna è numerica in questo caso, ma sarei interessato a sapere se c'era un modo per farlo con le colonne di stringhe.

Per questa particolare applicazione, il checksum non deve essere crittograficamente sicuro.

risposta

2

sembra che si potrebbe anche usare crc32 invece di md5 se non si cura di forza crittografica. Penso che questo:

select sum(crc32(some_column)) from some_table; 

funzionerebbe su stringhe. Potrebbe essere inefficiente in quanto forse MySQL creerebbe una tabella temporanea (specialmente se hai aggiunto un order by).

+0

'SUM()' Non è la cosa giusta da usare qui, poiché due checksum diversi potrebbero sommare allo stesso valore abbastanza facilmente –

+0

Come evitare un overflow numerico con questo approccio? – Robert

1

Se la colonna è numerico, si potrebbe fare questo:

SELECT BIT_XOR(mycolumn) + SUM(mycolumn) 

Naturalmente questo è facile da sconfiggere, ma includerà tutti i bit della colonna.

3
SELECT crc 
FROM 
(
    SELECT @r := MD5(CONCAT(some_column, @r)) AS crc, 
     @c := @c + 1 AS cnt 
    FROM 
    (
    SELECT @r := '', @c := 0 
    ) rc, 
    (
    SELECT some_column 
    FROM mytable 
    WHERE condition = TRUE 
    ORDER BY 
     other_column 
    ) k 
) ci 
WHERE cnt = @c 
4

La query seguente viene utilizzata nello strumento di checksum della tabella Mysql di Percona. È un po 'difficile da capire, ma in sostanza è CRC32 s la colonna (o un mucchio di colonne concatenate) per ogni riga, quindi XOR s tutte insieme utilizzando la funzione di gruppo BIT_XOR. Se un hash crc è diverso, il risultato di XOR in tutto sarà anche diverso. Questo accade nella memoria fissa, quindi puoi checksum tabelle di dimensioni arbitrarie.

SELECT CONV(BIT_XOR(CAST(CRC32(column) AS UNSIGNED)), 10, 16)

Una cosa da tenere a mente però che questo non impedisce possibili collisioni, e CRC32 è una funzione piuttosto debole per gli standard odierni. Una funzione di hashing più gradevole sarebbe qualcosa come lo FNV_64. Sarebbe molto improbabile avere due hash che si completano a vicenda quando XOR ed insieme.

Problemi correlati