Postgresの高速ハミング距離クエリ


15

画像のハッシュを含む大規模なデータベース(16M行)があります。

妥当な時間枠で距離ハミングすることで行を検索できるようにしたいと思います。

現在、私が問題を適切に理解している限り、ここでの最良の選択肢はBK-Treeを実装するカスタムSP-GiST実装だと思いますが、それは多くの作業のように思われ、まだ実用的ではありませんカスタムインデックスの適切な実装の詳細。ハミング距離を計算すると、扱いやすい十分です、と私はやるけれども、Cを知っています。

基本的に、ここでの適切なアプローチは何ですか?ハッシュの特定の編集距離内で一致を照会できる必要があります。私が理解しているように、等しい長さの文字列を持つレーベンシュタイン距離は機能的にハミング距離です。そのため、そこからインデックスを作成する明確な方法はありませんが、少なくともいくつかの既存のサポートがあります(私が照会している値を思い出してください)変更:固定値からの距離を事前に計算することはできません。

ハッシュは現在、ハッシュのバイナリASCIIエンコード(たとえば「10010101 ...」)を含む64文字の文字列として格納されていますが、十分簡単に​​int64に変換できます。本当の問題は、比較的高速にクエリできる必要があるということです。

私が望むものの線に沿って何かを達成することは可能だと思わpg_trgmれますが、トライグラムマッチングメカニズムがどのように機能するかについては少しわかりません(特に、それが返す類似性メトリックは実際に何を表しますか?編集距離のようなもの)。

挿入のパフォーマンスは重要ではありません(各行のハッシュを計算するのは非常に計算コストがかかります)ので、私は主に検索を気にします。



@NeilMcGuigan-面白い!そこの最初のプレゼンテーションは、実際にはpostgresでSP-GiSTおよびGISTシステムを保守している人々からのものです。
偽の名前14

ただし、最初のリンクは根本的に異なるものです。彼らは集合交差点を探していますが、私はハミング距離を探しています。フェーズを組み合わせて1つのセットにまとめることはできますが、非常に面倒であり、他のすべての場所で多くのサポートコードが必要になります。
偽の名前14

FWIW、この時点で、私は自分のインデックス作成システムを実装する必要があると多かれ少なかれ結論づけました。現在、カスタムSP-GiSTインデックスを検討していますが、何をしているのかわかりません。
フェイクネーム

1
@FakeName:ハミング距離とは、画像ではなく、ハッシュ値の文字列のハミング距離を意味すると仮定していますか?言い換えれば、あなたは尋ねるために探している:Xビット置換が離れて入力パラメータからであるすべてのハッシュ値の検索
トーマスKejser

回答:


11

さて、私はカスタムpostgres C拡張の作成にしばらく時間を費やし、メモリ内にBKツリー構造を維持するCythonデータベースラッパーを作成するだけで終わりました。

基本的に、データベースからのphash値のメモリ内コピーを維持し、データベースへのすべての更新がBKツリーに再生されます。

ここではすべてgithubにあります。また、単体テストも多数あります。

距離が4のアイテムの1,000万個のハッシュ値のデータセット全体でクエリを実行すると、ツリーの値の〜0.25%-0.5%がタッチされ、〜100ミリ秒かかります。


メモリ内に1600万行があるメモリ内のBKツリー?私は似たようなものを見ていましたが、各画像に1000個の画像と2000個の記述子があり、メモリサイズは巨大でした。
スチュワート

@Stewart-これの多くはハッシュのサイズに依存します。私の場合、ハッシュ値の出力は、int64として保存する単一の64ビットビットフィールドです。はるかに大きいphashデータ型があるようです。また、そのような異なるデータ型で検索がどのように機能するのかもわかりません。それらはまだメトリック空間ですか?距離はどのように計算しますか?
偽の名前

opencvで提供されるFLANN marcherで32ビット記述子を使用しています。距離を計算するには、Loweの比率に基づいたしきい値でハミングを使用します。この時点で、KDツリー構造を提供するメモリFLANNを使用するのが最善か、それともより類似したソリューションに切り替えるのが最善かどうかはわかりません。なぜあなたは自分自身を転がして、libflannのようなものに行かないのですか?
スチュワート

@Stewart-私は自分で転がしませんでした。私は、超退屈なDFTベースのハッシュを使用しています。
偽の名前

7

モアーの回答!

さて、ついに時間をかけてカスタムPostgreSQLインデックス拡張機能を作成しました。SP-GiSTインターフェースを使用しました。

主にPosgresが大きいため、これはかなり困難でした。

とにかく、いつものように、ここの githubにあります

パフォーマンスに関しては、現在、この質問に対する他の回答のメモリ内の実装よりも2〜3倍遅いですが、使用する方がはるかに便利ですので、そのパフォーマンスヒットを喜んで食べます(現実的には、50 ms / query-150 ms / query、これはまだかなり小さいです)。


あなたは素晴らしいです!インストール方法に関するREADMEを追加できますか?Postgresに実際に何もインストールしたことはありませんでした:P
HypeWolf

1
@HypeWolf-リポジトリのルートにはREADMEがあります。それはあなたが望むものをカバーしていませんか?
フェイクネーム

私の間違い、私はそれを見なかった、私はどこを見ているのかわからない:/
HypeWolf

READMEも探していました。ルートフォルダーにあります。リンクはいくつかのサブフォルダーに移動します。それは紛らわしかった。
ラッキードナルド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.