我基本上准备短语被放入数据库,他们可能是畸形的,所以我想要存储他们的一个短哈希代替(我将只是比较他们是否存在,所以哈希是理想的)。
我假设MD5在100,000+请求时相当慢,所以我想知道什么是哈希短语的最佳方法,也许是推出我自己的哈希函数或使用哈希('md4', '…“最终会更快吗?”
我知道MySQL有MD5(),所以这将在查询端补充一点速度,但也许在MySQL中还有一个更快的哈希函数,我不知道这将与PHP一起工作。
我基本上准备短语被放入数据库,他们可能是畸形的,所以我想要存储他们的一个短哈希代替(我将只是比较他们是否存在,所以哈希是理想的)。
我假设MD5在100,000+请求时相当慢,所以我想知道什么是哈希短语的最佳方法,也许是推出我自己的哈希函数或使用哈希('md4', '…“最终会更快吗?”
我知道MySQL有MD5(),所以这将在查询端补充一点速度,但也许在MySQL中还有一个更快的哈希函数,我不知道这将与PHP一起工作。
当前回答
fcn time generated hash
crc32: 0.03163 798740135
md5: 0.0731 0dbab6d0c841278d33be207f14eeab8b
sha1: 0.07331 417a9e5c9ac7c52e32727cfd25da99eca9339a80
xor: 0.65218 119
xor2: 0.29301 134217728
add: 0.57841 1105
生成这个的代码是:
$loops = 100000;
$str = "ana are mere";
echo "<pre>";
$tss = microtime(true);
for($i=0; $i<$loops; $i++){
$x = crc32($str);
}
$tse = microtime(true);
echo "\ncrc32: \t" . round($tse-$tss, 5) . " \t" . $x;
$tss = microtime(true);
for($i=0; $i<$loops; $i++){
$x = md5($str);
}
$tse = microtime(true);
echo "\nmd5: \t".round($tse-$tss, 5) . " \t" . $x;
$tss = microtime(true);
for($i=0; $i<$loops; $i++){
$x = sha1($str);
}
$tse = microtime(true);
echo "\nsha1: \t".round($tse-$tss, 5) . " \t" . $x;
$tss = microtime(true);
for($i=0; $i<$loops; $i++){
$l = strlen($str);
$x = 0x77;
for($j=0;$j<$l;$j++){
$x = $x xor ord($str[$j]);
}
}
$tse = microtime(true);
echo "\nxor: \t".round($tse-$tss, 5) . " \t" . $x;
$tss = microtime(true);
for($i=0; $i<$loops; $i++){
$l = strlen($str);
$x = 0x08;
for($j=0;$j<$l;$j++){
$x = ($x<<2) xor $str[$j];
}
}
$tse = microtime(true);
echo "\nxor2: \t".round($tse-$tss, 5) . " \t" . $x;
$tss = microtime(true);
for($i=0; $i<$loops; $i++){
$l = strlen($str);
$x = 0;
for($j=0;$j<$l;$j++){
$x = $x + ord($str[$j]);
}
}
$tse = microtime(true);
echo "\nadd: \t".round($tse-$tss, 5) . " \t" . $x;
其他回答
警告
下面的答案没有回答所问的问题,因为它不推荐哈希函数。记住,“哈希函数是可以用来将任意大小的数据映射到固定大小值的任何函数。”(维基百科)下面的答案建议转换不能保证固定大小的结果。
如果您愿意放宽使用哈希函数的要求,请继续阅读…
原来的答案
出于以下原因,我建议使用urlencode()或base64_encode():
不需要密码学 你需要速度 您需要一种方法来识别唯一的字符串,同时清理“畸形”字符串
在这些回复的其他地方调整基准代码,我已经证明了这两种方法都比任何哈希算法快得多。取决于你的应用程序,你可以使用urlencode()或base64_encode()清理任何你想要存储的“畸形”字符串。
第一步:安装libsodium(或确保您使用的是PHP 7.2+)
第二步:使用以下方法之一:
sodium_crypto_generichash(),即BLAKE2b,这是一个比MD5更安全但比SHA256更快的哈希函数。(Link有基准测试等) sodium_crypto_shorthash(),它是SipHash-2-4,适用于哈希表,但不应该依赖于抗碰撞。
_shorthash的速度大约是_generichash的3倍,但是您需要一个密钥,并且存在较小但现实的碰撞风险。使用_generichash,您可能不需要担心冲突,也不需要使用键(但无论如何都可能需要)。
在哈希中实现md5比md5()快一点。 所以这可以是一个选项或其他,请尝试:
echo '<pre>';
$run = array();
function test($algo)
{
#static $c = 0;
#if($c>10) return;
#$c++;
$tss = microtime(true);
for($i=0; $i<100000; $i++){
$x = hash($algo, "ana are mere");
}
$tse = microtime(true);
$GLOBALS['run'][(string)round($tse-$tss, 5)] = "\nhash({$algo}): \t".round($tse-$tss, 5) . " \t" . $x;
#echo "\n$i nhash({$algo}): \t".round($tse-$tss, 5) . " \t" . $x;
}
array_map('test', hash_algos());
ksort($run);
print_r($run);
echo '</pre>';
你可以在http://www.dozent.net/Tipps-Tricks/PHP/hash-performance上看到
Adler32在我的机器上运行得最好。 md5()比crc32()更快。
+-------------------+---------+------+--------------+
| NAME | LOOPS | TIME | OP/S |
+-------------------+---------+------+--------------+
| sha1ShortString | 1638400 | 2.85 | 574,877.19 |
| md5ShortString | 2777680 | 4.11 | 675,834.55 |
| crc32ShortString | 3847980 | 3.61 | 1,065,922.44 |
| sha1MediumString | 602620 | 4.75 | 126,867.37 |
| md5MediumString | 884860 | 4.69 | 188,669.51 |
| crc32MediumString | 819200 | 4.85 | 168,907.22 |
| sha1LongString | 181800 | 4.95 | 36,727.27 |
| md5LongString | 281680 | 4.93 | 57,135.90 |
| crc32LongString | 226220 | 4.95 | 45,701.01 |
+-------------------+---------+------+--------------+
似乎crc32对于较小的消息(在本例中为26个字符)更快,而md5对于较长的消息(在本例中为>852个字符)。