创建一个列的聚合校验和

问题描述:

我想计算一个聚合列中所有值的校验和。创建一个列的聚合校验和

换句话说,我想要做的

md5(group_concat(some_column)) 

一些等效采用这种方法的问题是:

  1. 这是低效的。在将其传递给md5函数之前,它必须将该列的所有值作为一个字符串连接起来。
  2. group_concat的最大长度为1024,之后所有其他内容都将被截断。

(如果你想知道,你能确保值的CONCAT是一致的顺序,但是,因为无论你相信与否GROUP_CONCAT()接受由内这条命令,如group_concat(some_column order by some_column))我提供了非标准的按位集合函数BIT_AND(),BIT_OR()和BIT_XOR(),我认为这对于这个问题是有用的。在这种情况下,列是数字,但我很想知道是否有方法使用字符串列来完成此操作。

对于这个特定的应用程序,校验和不必是安全的。

好像你还不如用crc32而不是md5如果你不关心加密强度。我认为这:

select sum(crc32(some_column)) from some_table; 

将工作的字符串。这可能是低效率的,因为MySQL可能会创建一个临时表(特别是如果您添加了order by)。

+0

SUM()`在这里使用是不正确的,因为两个不同的校验和可以很容易地总结到相同的值 – 2013-04-15 19:11:21

如果列数字,你可以这样做:

SELECT BIT_XOR(mycolumn) + SUM(mycolumn) 

当然,这是容易失败,但它会包括在列中的所有位。

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 

以下查询用于Percona的Mysql Table Checksumming工具。它有点难以理解,但本质上它是针对每一行的列(或一串列连续),然后使用BIT_XOR组函数将它们全部组合在一起。如果一个crc散列值不同,则所有的结果都会不同。这发生在固定的内存中,所以你可以校验任意大的表。

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

有一点要记住,虽然这并不能阻止可能发生的碰撞,并CRC32是今天的标准相当薄弱的功能。一个更好的散列函数就像FNV_64。当将XOR编辑在一起时,将不太可能具有互补的两个散列。