Быстрые дистанционные запросы Хемминга в postgres

15

У меня есть большая база данных (16 миллионов строк), содержащая перцептивные хеши изображений.

Я хотел бы иметь возможность искать строки по расстоянию Хэмминга в разумные сроки.

В настоящее время, насколько я правильно понимаю проблему, я думаю, что лучшим вариантом здесь была бы пользовательская реализация SP-GiST, которая реализует BK-Tree , но это кажется большой работой, и я все еще не совсем уверен в практической детали правильной реализации пользовательского индекса. Расчет расстояния Хэмминга достаточно податлив, и я все же знаю C.

В принципе, то , что является подходящим подходом здесь? Мне нужно иметь возможность запрашивать совпадения в пределах определенного расстояния редактирования хэша. Насколько я понимаю, расстояние Левенштейна со строками равной длины - это функциональное расстояние Хемминга, так что есть, по крайней мере, некоторая существующая поддержка того, что я хочу, хотя нет четкого способа создать из него индекс (помните, значение, которое я запрашиваю для изменения. Я не могу предварительно вычислить расстояние от фиксированного значения, так как это было бы полезно только для этого одного значения).

Хеши в настоящее время хранятся в виде строки из 64 символов, содержащей двоичную ASCII-кодировку хеша (например, «10010101 ...»), но я могу достаточно легко преобразовать их в int64. Реальная проблема в том, что мне нужно уметь делать запросы относительно быстро.

Кажется, что можно достичь чего-то в соответствии с тем, что я хочу с помощью pg_trgm, но мне немного неясно, как работает механизм сопоставления триграмм (в частности, что на самом деле представляет метрика сходства, которую он возвращает ? вроде как расстояние редактирования).

Производительность вставки не критична (вычислять хэши для каждой строки очень дорого в вычислительном отношении), поэтому я в первую очередь забочусь о поиске.

Поддельное имя
источник
Расширение smlar может иметь то, что вам нужно: pgcon.org/2012/schedule/attachments/252_smlar-2012.pdf или pg_sdentifity: pgcon.org/2009/schedule/attachments/108_pg_sdentifity.pdf
Нил Макгиган
@NeilMcGuigan - Интересно! Первая презентация там на самом деле от людей, которые поддерживают системы SP-GiST и GIST в postgres.
Фальшивое имя
Первая ссылка для чего-то принципиально иного. они ищут установленные пересечения, в то время как я ищу расстояние Хэмминга. Я мог бы заключить phash в набор, но это было бы очень грязно и потребовало бы много кода поддержки везде.
Фальшивое имя
FWIW, На данный момент я более или менее пришел к выводу, что мне нужно реализовать собственную систему индексации. Сейчас я изучаю пользовательские индексы SP-GiST, но понятия не имею, что я делаю.
Фальшивое имя
1
@FakeName: Когда вы говорите расстояние Хемминга, я предполагаю, что вы имеете в виду расстояние Хемминга строк хеш-значений, а не изображений? Другими словами, вы хотите спросить: Найти все значения хеш-функции, которые являются X-битными заменами от входного параметра
Томас Кейсер

Ответы:

11

Что ж, я потратил некоторое время на то, чтобы написать собственное расширение C для postgres, и занялся написанием оболочки базы данных Cython, которая поддерживает структуру BK-дерева в памяти.

По сути, он поддерживает в памяти копию значений phash из базы данных, и все обновления базы данных воспроизводятся в BK-дереве.

Это все на github здесь . Он также имеет множество юнит-тестов.

Запрос по набору данных из 10 миллионов значений хеш-функции для элементов с расстоянием 4 приводит к касанию ~ 0,25% -0,5% значений в дереве и занимает ~ 100 мс.

Поддельное имя
источник
BK-дерево в памяти с 16 миллионами строк в памяти? Я смотрел на что-то подобное, однако с 1000 изображений и 2000 дескрипторов на каждом изображении мой объем памяти был огромен.
Стюарт
@Stewart - Многое зависит от размера вашего хэша. В моем случае вывод хеш-значения - это одно 64-битное битовое поле, которое я сохраняю как int64. Похоже, у вас гораздо больший тип данных phash. Я также не уверен, как поиск будет работать на другом типе данных, как это. Они все еще метрическое пространство? Как вы рассчитываете расстояние?
Поддельное имя
Я использую 32-битные дескрипторы с маршером FLANN, поставляемым с opencv. Для расчета расстояния я использую хемминга с порогом на основе отношения Лоу. На данный момент я не уверен, стоит ли пытаться придерживаться в памяти FLANN, которая предоставляет структуру KD-дерева, или переключаться на решение, более похожее на ваше. Почему вы закончили тем, что катались, а не шли за чем-то вроде libflann?
Стюарт
@ Стюарт - я не катил свой собственный. Я использую супер скучное хеширование на основе DFT .
Фальшивое имя
7

МОРА ОТВЕТЫ!

Хорошо, я наконец-то нашел время для написания собственного индексационного расширения PostgreSQL. Я использовал интерфейс SP-GiST .

Это было довольно сложно, в основном из-за того, что Posgres большой .

В любом случае, как обычно, это на github здесь .

Что касается производительности, то в настоящее время она примерно в 2-3 раза медленнее, чем реализация в памяти, как в моем другом ответе на этот вопрос, но это гораздо удобнее в использовании, и я с удовольствием воспользуюсь этим снижением производительности (реально, это ~ 50 мс / запрос - 150 мс / запрос, что все еще довольно мало).

Поддельное имя
источник
Ты обалденный! Можете ли вы добавить README о том, как установить? Я действительно никогда ничего не устанавливал в Postgres: P
HypeWolf
1
@HypeWolf - Корень репо имеет README . Разве это не покрывает то, что вы хотите?
Поддельное имя
Моя ошибка, я не видел ее, я не уверен, где я искал: /
HypeWolf
Искал README также. Это в корневой папке. Ссылка идет в какую-то подпапку. Это сбивало с толку.
luckydonald