我在MySQL MyISAM表中存储了唯一的用户代理,所以当我必须查看表中是否存在时,我会检查 md5哈希存储在TEXT字段旁边。
User-Agents
{
id - INT
user-agent - TEXT
hash - VARCHAR(32) // md5
}
有什么方法可以做同样但使用32位整数而不是文本哈希?也许原始格式的md5会更快?这将需要二元搜索。
[编辑]
MySQL不处理完整区分大小写的字符串的哈希搜索?
答案 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的BINARY
和VARBINARY
类型。见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位值没有任何意义......