背景
我们正在构建一个邮件工具,目前已将emailaddresses
分隔为一个单独的表,因此单个emailaddress
只存储一次,而是由id
引用。我们发现这是一个好主意,因为每封电子邮件的收件人数量可能很大,并且很可能大多数电子邮件都会收到超过100封电子邮件。
但是,当用户将emailaddresses
导入list
或类似操作时,我们首先需要批量插入以确保所有电子邮件都有ids
,我们只是忽略冲突,这样可行。但是,当我们想要将它们插入list
时,我们必须逐个获取emailaddresses
或使用emailaddresses进行大量的IN查询(作为list
引用{ {1}} emailaddress
},不是很诱人!
编辑:用户可能正在导入100.000+个电子邮件地址,对于1000个左右的电子邮件地址来说,当然一个一个地查询并不是一个真正的问题。
问题:
因此,一个想法是对每个id
进行哈希处理,并将其用作emailaddress
。这意味着,我们可以预测所有id
的{{1}},而无需查询它们。但是有没有好的算法,因为存储16bytes / 128bit +有点失败的目的...... 64bit 应该足够吗?鉴于这一切都应该被编入索引,我们将不胜感激。
有什么建议吗?如果我们只是从MD5中获取前8个字节怎么办? SHA1的8字节更好吗?也许还有更专业的算法?我并不是所有人都知道碰撞概率,但我很好奇现有算法在裁剪时的效果如何,以及电子邮件是小写的,主要是字母或数字。 (注意数据集可能很大)
PS。我们正在使用PHP,因此它在一定程度上限制了我们实现特殊算法的能力。
答案 0 :(得分:1)
我不确定我理解您的用例,但在电子邮件地址栏中添加了一个唯一的键约束...
答案 1 :(得分:0)
您当前的方法及其局限性存在很多问题。
其中大部分都可以通过维护一个电子邮件地址表来解决,其中ID为主键(MySQL或SQLite上的自动增量,其他地方的序列)和电子邮件地址上的唯一索引。
为什么你的“用户”正在操纵大量的电子邮件地址列表还远未明朗。听起来您的数据中有很大一部分(即特定列表中的收件人)未在您的数据库中维护。你永远不应该“通过emailaddresses逐个获取电子邮件地址或使用巨大的IN查询”。
减少md5或sha的输出会破坏哈希的唯一性,并且更容易发生冲突。
答案 2 :(得分:0)
在您做任何激烈的事情之前,请检查您的查询计划(如何执行此操作取决于您使用的特定数据库服务器,请查看其文档)。
查看您是否无法获取索引以处理电子邮件地址。这应该可以加快速度,但规划人员可能会跳过它们,因为你要插入大量数据。
当你尝试过这种情况时,你可以查看散列问题。
我不知道任何专门用于散列电子邮件地址的算法,虽然您可以使用MD5,但是当碰撞的概率必须非常小而基本上从未发生时,它被设计用于(我不认为有人有在野外发现了MD5碰撞)。这可以做到,但计算成本很高。如果使用SHA,情况会更糟。
在你的情况下,我会建议一些更简单的事情:首先,因为我们可以假设所有电子邮件都是
形式<someName>@<someServer>
我会做的是将电子邮件分成两部分,从每个部分中删除所有非字母,非数字字符。
接下来我们可以计算这两个部分中每个部分的数值,我们通过总结每个单独字母的ascii值得到(你剥离了其他所有部分,因此多字节字符不会出现问题)
此时剩下要做的就是合并两个总和,因为我们可以预期会有更少的可能发送者,我们只能花两个字节来保存服务器的名称。
在伪代码中:
function emailHash(namePart, serverPart){
$someName = asciiStrip(namePart)
$someServer = asciiStrip(serverPart)
$someNameSum = 0
$someServerSum = 0
foreach($letter in $someName){
$someNameSum += asciiValue($letter)
}
foreach($letter in $someServer){
$someServerSum += asciiValue($letter)
}
return ($someNameSum % 2^6)*2^2 + $someServerSum % 2^2
}
根据评论进行修改
你是对的,那个人真的很穷。然而,你可以做另一个有趣的事情,虽然实施起来会有点困难。
在剥离外来字符后,只有36个可能的字符,所以我们只需要6位来存储每个值。用户名部分有48位存储空间,可以从电子邮件地址存储8个字符。碰撞到底有多低?
可以通过某种方式取消数字(比如将它们除以2后存储它们)来改进,这样我们总共只处理32个数字。然后,可以将每个数字仅存储5位,总共9个字符。
如果这不能提供足够低的碰撞率,你可能不得不使用MD5(假设算法给出了完美的分布),只能给你几十亿的碰撞机会。