Szybkie zapytania o odległość uderzenia w postgresie

15

Mam dużą bazę danych (16M wierszy) zawierającą percepcyjne skróty obrazów.

Chciałbym móc wyszukiwać rzędy, zbijając odległość w rozsądnym czasie.

Obecnie, o ile dobrze rozumiem ten problem, myślę, że najlepszą opcją jest niestandardowa implementacja SP-GiST, która implementuje drzewo BK , ale wydaje się, że to dużo pracy, i wciąż jestem rozmyślany nad praktycznymi szczegóły dotyczące prawidłowego wdrażania indeksu niestandardowego. Obliczanie odległości uderzenia jest wystarczająco łatwe, ale znam C.

Zasadniczo, jakie jest tutaj właściwe podejście? Muszę być w stanie wyszukiwać dopasowania w obrębie określonej odległości edytowania skrótu. Jak rozumiem, odległość Levenshteina z łańcuchami o równej długości jest funkcjonalnie hamująca odległość, więc istnieje co najmniej pewne wsparcie dla tego, czego chcę, chociaż nie ma jasnego sposobu na utworzenie z niego indeksu (pamiętaj, o wartość, o którą pytam zmiany. Nie mogę wstępnie obliczyć odległości od stałej wartości, ponieważ byłoby to przydatne tylko dla tej jednej wartości).

Skróty są obecnie przechowywane jako 64-znakowy ciąg zawierający binarne kodowanie skrótu ASCII (np. „10010101 ...”), ale dość łatwo mogę przekonwertować je na int64. Prawdziwy problem polega na tym, że muszę stosunkowo szybko przesyłać zapytania.

Wydaje się, że można osiągnąć coś zgodnie z tym, czego chcę pg_trgm, ale nie jestem pewien, jak działa mechamizm dopasowywania trygramu (w szczególności, co w rzeczywistości reprezentuje wskaźnik podobieństwa, który zwraca ? coś w rodzaju odległości do edycji).

Wydajność wstawiania nie jest krytyczna (obliczanie wartości skrótu dla każdego wiersza jest bardzo drogie obliczeniowo), więc przede wszystkim zależy mi na wyszukiwaniu.

Zmyślone imię
źródło
Rozszerzenie smlar może mieć to, czego potrzebujesz: pgcon.org/2012/schedule/attachments/252_smlar-2012.pdf lub pg_similarity: pgcon.org/2009/schedule/attachments/108_pg_similarity.pdf
Neil McGuigan
@NeilMcGuigan - Ciekawe! Pierwsza prezentacja pochodzi od osób, które utrzymują systemy SP-GiST i GIST w postgresie.
Fałszywe imię
Pierwszy link dotyczy jednak czegoś zupełnie innego. szukają ustalonych skrzyżowań, podczas gdy ja szukam odległości uderzenia. Mógłbym sflashować lampy błyskowe na zestaw, ale byłoby to bardzo nieuporządkowane i wymagałoby dużo kodu wsparcia wszędzie indziej.
Fałszywe imię
FWIW, W tym momencie mniej więcej doszedłem do wniosku, że muszę wdrożyć własny system indeksowania. Obecnie szukam niestandardowych wskaźników SP-GiST, ale nie mam pojęcia, co robię.
Fałszywe imię
1
@FakeName: Kiedy mówisz o odległości Hamminga, zakładam, że masz na myśli odległość Hamminga łańcuchów wartości skrótu, a nie obrazów? Innymi słowy, chcesz zapytać: Znajdź wszystkie wartości skrótu, które są podstawieniami bitów X od parametru wejściowego
Thomas Kejser

Odpowiedzi:

11

Cóż, poświęciłem chwilę na napisanie niestandardowego rozszerzenia Postgres C i skończyło się na napisaniu opakowania bazy danych Cython, które zachowuje strukturę drzewa BK w pamięci.

Zasadniczo przechowuje w pamięci kopię wartości phash z bazy danych, a wszystkie aktualizacje bazy danych są odtwarzane w drzewie BK.

Wszystko jest tutaj na githubie . Ma również wiele testów jednostkowych.

Zapytanie w zbiorze danych zawierającym 10 milionów wartości skrótu dla elementów o odległości 4 powoduje dotknięcie ~ 0,25% -0,5% wartości w drzewie i zajmuje ~ 100 ms.

Zmyślone imię
źródło
BK-Tree w pamięci z 16 milionami wierszy w pamięci? Patrzyłem na coś podobnego, jednak z 1000 obrazami i 2000 deskryptorami na każdym obrazie mój rozmiar pamięci był ogromny.
Stewart
@Stewart - Wiele z tego zależy od wielkości twojego skrótu. W moim przypadku wartością wyjściową wartości skrótu jest pojedyncze 64-bitowe pole bitowe, które przechowuję jako int64. Wygląda na to, że masz znacznie większy typ danych phash. Nie jestem również pewien, jak wyszukiwania będą działać na innym rodzaju danych tego typu. Czy nadal są przestrzenią metryczną? Jak obliczyć odległość?
Fałszywe imię
Używam 32-bitowych deskryptorów z marszerem FLANN dostarczanym z opencv. Aby obliczyć odległość, używam młota z progiem opartym na współczynniku Lowe'a. W tym momencie nie jestem pewien, czy najlepiej jest spróbować pozostać w pamięci FLANN, który zapewnia strukturę drzewa KD, czy przejść do rozwiązania bardziej podobnego do twojego. Dlaczego skończyłeś sam i nie wybierasz czegoś takiego jak libflann?
Stewart
@Stewart - nie wyrzuciłem własnego. Używam super nudnego mieszania opartego na DFT .
Fałszywe imię
7

MOAR ODPOWIEDZI!

Ok, w końcu poświęciłem czas na napisanie niestandardowego rozszerzenia do indeksowania PostgreSQL. Użyłem interfejsu SP-GIST .

Było to dość trudne, głównie dlatego, że Posgres jest duży .

W każdym razie, jak zwykle, jest tutaj na github .

Pod względem wydajności jest obecnie ~ 2-3 razy wolniejsza niż implementacja czysta w pamięci w mojej innej odpowiedzi na to pytanie, ale jest o wiele wygodniejsza w użyciu Z przyjemnością zjem ten hit wydajności (realistycznie, to ~ 50 ms / zapytanie - 150 ms / zapytanie, które wciąż jest dość małe).

Zmyślone imię
źródło
Jesteś niesamowity! Czy możesz dodać plik README na temat instalacji? Nigdy tak naprawdę nic nie instalowałem w Postgres: P
HypeWolf
1
@HypeWolf - katalog główny repozytorium ma plik README . Czy to nie obejmuje tego, czego chcesz?
Fałszywe imię
Mój błąd, nie widziałem go, nie jestem pewien, gdzie szukałem: /
HypeWolf
Szukał również README. Jest w folderze głównym. Link przechodzi do jakiegoś podfolderu. To było mylące.
luckydonald