Postgres中的快速汉明距离查询


15

我有一个大型数据库(1600万行),其中包含图像的感知哈希。

我希望能够在合理的时间内按汉明距离搜索行。

目前,据我所知,我认为最好的选择是自定义SP-GiST实现,该实现可实现BK-Tree,但这似乎需要大量工作,但我仍然对实用性感到困惑正确实现自定义索引的详细信息。计算汉明距离很容易,但是我确实知道C。

基本上,这里合适的方法是什么?我需要能够在哈希的特定编辑距离内查询匹配项。据我了解,长度相等的字符串的Levenshtein距离在功能上是汉明距离,因此,尽管没有明确的方法可以从中创建索引(请记住,我正在查询的值),至少存在一些对我想要的支持。我无法预先计算与固定值的距离,因为那只会对那个值有用。

哈希当前存储为64个字符的字符串,其中包含哈希的二进制ASCII编码(例如“ 10010101 ...”),但是我可以很容易地将它们转换为int64。真正的问题是我需要能够相对快速地进行查询。

似乎可以通过达成与我想要的目标类似的东西pg_trgm,但是我不清楚三联词匹配机制的工作原理(特别是,它返回的相似性度量实际上代表了什么?看起来有点像编辑距离)。

插入性能并不关键(计算每行的哈希值在计算上非常昂贵),因此我主要关心搜索。



@NeilMcGuigan-有趣!实际上,第一个演示文稿来自在postgres中维护SP-GiST和GIST系统的人员。
假名称

但是,第一个链接是针对根本不同的东西。他们在寻找路口,而我在寻找汉明距离。我可以将这些短语整理成一个集合,但这将非常混乱,并且在其他地方都需要很多支持代码。
假名称

FWIW,在这一点上,我或多或少地得出结论,我需要实现自己的索引系统。我目前正在研究自定义SP-GiST索引,但是我不知道自己在做什么。
假名称

1
@FakeName:当您说汉明距离时,我假设您是指哈希值字符串而不是图像的汉明距离?换句话说,您要询问:查找所有远离输入参数X位替换的哈希值
Thomas Kejser 2014年

Answers:


11

好吧,我花了一段时间看待编写自定义的postgres C扩展,最后写了一个Cython数据库包装器,该包装器在内存中维护了BK树结构。

基本上,它维护数据库中phash值的内存副本,并且对数据库的所有更新都将重播到BK树中。

全部都在这里的 github上。它还有很多单元测试。

在1000万个散列值的数据集中查询距离为4的项会导致触摸树中〜0.25%-0.5%的值,大约需要100毫秒。


内存中的BK树有1600万行?我当时在看类似的东西,但是每个图像上有1000个图像和2000个描述符,我的内存容量很大。
斯图尔特

@Stewart-这在很大程度上取决于哈希的大小。就我而言,哈希值输出是一个64位位域,我将其存储为int64。您似乎具有更大的phash数据类型。我也不确定如何在类似的其他数据类型上进行搜索。他们仍然是公制空间吗?您如何计算距离?
假名称

我将32位描述符与opencv提供的FLANN marcher一起使用。为了计算距离,我使用基于Lowe比率的海明阈值。此时,我不确定是否最好尝试在内存中使用FLANN,它提供KD-tree结构或切换到与您的解决方案更相似的解决方案。为什么最终自己滚动而不选择libflann之类的东西?
斯图尔特

@Stewart-我没有自己动手。我正在使用基于DFT的超无聊哈希
假名称

7

沼泽答案!

好的,我终于花了时间写一个自定义的PostgreSQL索引扩展。我使用了SP-GiST接口

这颇具挑战性,主要是因为Posgres 很大

无论如何,和往常一样,它在github 这里

在性能方面,目前比我在此问题的其他答案中的纯内存实现慢大约2-3倍,但是使用起来要方便得多,我会很高兴地吃掉性能下降带来的麻烦(实际上大约是50毫秒/查询-150毫秒/查询,这仍然很小)。


你真棒!您可以添加有关如何安装的自述文件吗?我从没真正在Postgres中安装任何东西:P
HypeWolf

1
@HypeWolf-存储库的根目录具有README。那不能满足您的需求吗?
假名称

我的错误,我没有看到,我不确定我在找什么:/
HypeWolf

也在寻找自述文件。在根文件夹中。该链接将转到某个子文件夹。那令人困惑。
luckydonald
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.