如何在不使用文本字段的情况下在MySQL数据库中存储哈希值

时间:2010-08-24 07:28:19

标签: php mysql hash md5

我在MySQL MyISAM表中存储了唯一的用户代理,所以当我必须查看表中是否存在时,我会检查 md5哈希存储在TEXT字段旁边。

User-Agents 
{
    id         - INT
    user-agent - TEXT
    hash       - VARCHAR(32) // md5
}

有什么方法可以做同样但使用32位整数而不是文本哈希?也许原始格式的md5会更快?这将需要二元搜索。

[编辑]

MySQL不处理完整区分大小写的字符串的哈希搜索?

9 个答案:

答案 0 :(得分:7)

UNHEX(MD5($value))存储在BINARY(16)

答案 1 :(得分:5)

你可以这样做:

User-Agents 
{
    id         - INT
    user-agent - TEXT
    hash       - UNSIGNED INT (CRC32, indexed)
}


$crc32 = sprintf("%u", crc32($user_agent));

SELECT * FROM user_agents WHERE hash=$crc32 AND user_agent='$user_agent';

这种数据不太可能与crc32发生冲突。

要确保冲突不会导致问题,请添加辅助搜索参数。 MySQL将能够使用索引快速查找记录。然后它可以进行简单的字符串搜索,以保证匹配正确。

PS:sprintf()用于处理带符号的32位整数。在64位系统上应该是不必要的。

答案 2 :(得分:4)

让MySQL为您付出艰苦的努力。在该列上使用CHAR列和create an index。您可以将哈希转换并存储为整数,但绝对没有任何好处,它实际上可能会导致问题。

答案 3 :(得分:3)

尝试MurmurHash。它是一种快速的哈希算法,已被翻译成多种语言。它接受您的输入并将其转换为32/64位整数散列。

答案 4 :(得分:2)

您无法在32位int中存储MD5哈希:它根本不适合。 (以十六进制写入时为32个字符,但它是128位数据)

您可以查看MySQL的BINARYVARBINARY类型。见http://dev.mysql.com/doc/refman/5.1/en/binary-varbinary.html。这些类型存储二进制数据。在你的情况下,BINARY(16)VARBINARY(16),但由于MD5哈希值总是16字节,后者似乎有点无意义。

答案 5 :(得分:1)

您可以在char(32)中存储MD5哈希,这比varchar(32)快一点。 也可以制作两个BIGINT字段,并在第一个字段中保留md5哈希的前半部分,在第二个字段中保留第二部分。

答案 6 :(得分:0)

你真的确定哈希只是32位吗? MD5是128位。将哈希值裁剪为前4或8个字节会大大增加冲突的风险。

答案 7 :(得分:0)

如果您的字段hash始终是PHP生成的MD5值,则可以安全地将其设置为CHAR(32)。这不应该影响查询的响应时间,除非您计划有数百万行,甚至最差! JOIN此字段的其他表格。底线是固定宽度列比可变宽度列好,所以如果你可以优化它。

关于将MD5更改为int值,请参阅this question;对此的结论是,如果您真的想将MD5更改为128位的int值,那么您也可以使用随机数而不是MD5!

答案 8 :(得分:0)

您是否尝试过创建BINARY(16)字段,并将md5($plaintext, true);的结果存储在其中?这可能有效,请确保您也将该字段编入索引。

因为尝试在32位中拟合128位值没有任何意义......