创建一个列的聚合校验和
我想计算一个聚合列中所有值的校验和。创建一个列的聚合校验和
换句话说,我想要做的
md5(group_concat(some_column))
一些等效采用这种方法的问题是:
- 这是低效的。在将其传递给md5函数之前,它必须将该列的所有值作为一个字符串连接起来。
- 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
)。
如果列数字,你可以这样做:
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
编辑在一起时,将不太可能具有互补的两个散列。
SUM()`在这里使用是不正确的,因为两个不同的校验和可以很容易地总结到相同的值 – 2013-04-15 19:11:21