2009-02-26 19 views
8

Quiero calcular una suma de comprobación de todos los valores de una columna en conjunto.Crear una suma de comprobación agregada de una columna

En otras palabras, quiero hacer algo equivalente a

md5(group_concat(some_column)) 

El problema con este enfoque es:

  1. Es ineficiente. Tiene que hacer coincidir todos los valores de la columna como una cadena en algún almacenamiento temporal antes de pasarlo a la función md5
  2. group_concat tiene una longitud máxima de 1024, después de lo cual todo lo demás se truncará.

(En caso de que se esté preguntando, puede asegurarse de que el concat de los valores está en un orden coherente, sin embargo, que aunque no lo crean GROUP_CONCAT() acepta una orden por la cláusula dentro de ella, por ejemplo group_concat(some_column order by some_column))

MySQL ofrece las funciones de agregado bit a bit no estándar BIT_AND(), BIT_OR() y BIT_XOR() que supongo que serían útiles para este problema. La columna es numérica en este caso, pero me gustaría saber si había una manera de hacerlo con columnas de cadenas.

Para esta aplicación en particular, la suma de verificación no tiene que ser criptológicamente segura.

Respuesta

2

Parece que también podría utilizar en lugar de crc32md5 si no se preocupan por la fuerza criptográfica. Creo que esto:

select sum(crc32(some_column)) from some_table; 

funcionaría en cadenas. Puede ser ineficiente ya que tal vez MySQL crearía una tabla temporal (especialmente si agregó un order by).

+0

'SUM()' No es lo correcto para usar aquí, ya que dos sumas de comprobación diferentes podrían sumar al mismo valor con bastante facilidad –

+0

¿Cómo se evita el desbordamiento numérico con este enfoque? – Robert

1

Si la columna es numérico, se puede hacer esto:

SELECT BIT_XOR(mycolumn) + SUM(mycolumn) 

Por supuesto, esto es fácil de derrotar, pero incluirá todos los bits de la columna.

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 siguiente consulta se usa en la herramienta Perco's Mysql Table Checksumming. Es un poco difícil de entender, pero esencialmente es CRC32 s la columna (o un grupo de columnas concatenadas) para cada fila, luego XOR s todas juntas utilizando la función de grupo BIT_XOR. Si un hash crc es diferente, el resultado de XOR ing todo también será diferente. Esto ocurre en la memoria fija, por lo que puede verificar la suma de tablas arbitrariamente grandes.

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

Una cosa a tener en cuenta sin embargo que esto no evita posibles colisiones y CRC32 es una función bastante débil para los estándares de hoy en día. Una función de hash más agradable sería algo así como FNV_64. Sería muy poco probable tener dos valores hash que se complementaran entre sí cuando XOR ed juntos.

Cuestiones relacionadas