【发布时间】:2011-06-14 04:57:45
【问题描述】:
我的数据库中有一个表,我将 SHA256 哈希值存储在 BINARY(32) 列中。我正在寻找一种方法来计算列中的条目与提供的值的汉明距离,例如:
SELECT * FROM table
ORDER BY HAMMINGDISTANCE(hash, UNHEX(<insert supplied sha256 hash here>)) ASC
LIMIT 10
(如果您想知道,字符串 A 和 B 的汉明距离定义为 BIT_COUNT(A^B),其中 ^ 是按位异或运算符,BIT_COUNT 返回二进制字符串中 1 的数量)。
现在,我知道 ^ 运算符和 BIT_COUNT 函数都只适用于整数,所以我想说可能唯一的方法是将二进制字符串分解为子字符串,将每个二进制子字符串转换为整数,计算汉明距离子串,然后将它们相加。问题在于它听起来非常复杂,效率不高,而且绝对不优雅。因此,我的问题是:您能提出更好的方法吗? (请注意,我使用的是共享主机,因此无法修改数据库服务器或加载库)
edit(1):显然在 PHP 中加载整个表并在那里进行计算是可能的,但我宁愿避免它,因为这个表可能会变得非常大。
edit(2):数据库服务器是 MySQL 5.1
edit(3):我下面的答案包含我刚才描述的代码。
edit(4):我刚刚发现使用 4 个 BIGINT 而非 BINARY(32) 来存储散列可以大大提高速度(快 100 倍以上)。请参阅下面我的答案的 cmets。
【问题讨论】:
-
如果这对找到更好的解决方案有用,也可以提出不同的方法来存储哈希值。
-
如果您将哈希存储在 8 个整数中(可能除了二进制存储之外),计算会变得容易得多。
-
我真的很好奇你为什么要计算距离:)
-
我正在处理一个分布式哈希表,并且需要该步骤来在其他节点上查找密钥(即,如果您在本地没有密钥,则将查询转发到 ID 为更接近键 - 更接近是根据汉明距离测量的);显然,ID 和密钥的长度相同(在我的情况下为 256 位)。
-
“表格可能会变得很大”是什么意思?是否可以接受具有足够功能的全扫描,或者您是否需要一种使用某些索引并避免全扫描的方法?
标签: sql mysql hash binary-data hamming-distance