Postgres'te hızlı çarpma mesafesi sorguları


15

Ben algısal görüntü karma içeren büyük bir veritabanı (16M satır) var.

Makul bir zaman aralığında mesafeyi sıkıştırarak satırları arayabilmek istiyorum .

Şu anda, sorunu doğru bir şekilde anladığım kadarıyla, buradaki en iyi seçeneğin bir BK Ağacı uygulayan özel bir SP-GiST uygulaması olacağını düşünüyorum , ancak bu çok fazla iş gibi görünüyor ve hala pratikte bulanıkım özel bir dizinin düzgün bir şekilde uygulanmasının ayrıntıları. Hamming mesafe hesaplama uysal yeter, ben yapmak olsa da, C biliyoruz.

Temel olarak, burada uygun yaklaşım nedir? Bir karma belirli bir düzenleme mesafesi içinde eşleşmeleri sorgulamak gerekir. Anladığım kadarıyla, eşit uzunlukta dizeleriyle Levenshtein mesafe işlevsel mesafe hamming, bu yüzden en azından orada bazı ne istiyorum için mevcut destek o (hatırlamak gelen net bir yolu, ben sorgulama ediyorum değer bir dizin oluşturmak için de, Sabit bir değerden olan mesafeyi önceden hesaplayamıyorum, çünkü bu sadece bir değer için yararlı olacaktır).

Karmalar şu anda karma ikili ASCII kodlamasını içeren 64 karakterlik bir dize olarak saklanır (örneğin "10010101 ..."), ancak bunları kolayca int64'e dönüştürebilirim. Asıl mesele, nispeten hızlı sorgulama yapabilmem gerekiyor.

Görünüşe göre pg_trgm, istediğim şeyin çizgileri boyunca bir şey elde etmek mümkün olabilir , ancak mechamizle eşleşen trigramın nasıl çalıştığından biraz emin değilim (özellikle, döndürdüğü benzerlik metriği gerçekten neyi temsil ediyor? düzenleme mesafesi gibi).

Ekleme performansı kritik değildir (her satır için karmaları hesaplamak çok hesaplı olarak pahalıdır), bu yüzden öncelikle aramayı önemsiyorum.



@NeilMcGuigan - İlginç! Buradaki ilk sunum aslında postgreslerde SP-GiST ve GIST sistemlerini koruyan insanlardan.
Sahte Adı

İlk bağlantı, temelde farklı bir şey içindir. ayarlı kavşaklar arıyorlar, oysa ben vurma mesafesini arıyorum. Fazları bir sete finanse edebilirdim, ama son derece dağınık olurdu ve başka her yerde çok fazla destek kodu gerektiriyordu.
Sahte Adı

FWIW, Bu noktada az çok kendi indeksleme sistemimi uygulamam gerektiğine karar verdim. Şu anda özel SP-GiST indekslerine bakıyorum, ama ne yaptığım hakkında hiçbir fikrim yok.
Sahte Ad

1
@FakeName: Çekme mesafesini söylediğinizde, görüntüleri değil, karma değer dizelerinin çekiçleme mesafesini kastettiğini varsayıyorum. Başka bir deyişle, sormak istiyorsunuz: Giriş parametresinden X bit ikameleri olan tüm hash değerlerini bulun
Thomas Kejser

Yanıtlar:


11

Özel bir postgres C uzantısı yazmak için biraz zaman harcadım ve sadece bellekte bir BK ağacı yapısını koruyan bir Cython veritabanı sarıcısı yazarak yaraladım.

Temel olarak, veritabanından phash değerlerinin bellek içi bir kopyasını tutar ve veritabanındaki tüm güncellemeler BK ağacında yeniden oynatılır.

Hepsi burada github üzerinde . Ayrıca çok sayıda birim testi vardır.

4 mesafesi olan öğeler için 10 milyon karma değer veri kümesinde sorgulama yapmak, ağaçtaki değerlerin ~% 0.25 -% 0.5'ine dokunmakla sonuçlanır ve ~ 100 ms sürer.


BK-Tree bellekte 16 milyon satır bellek var mı? Bununla birlikte, benzer bir şeye bakıyordum 1000 görüntü ve 2000 tanımlayıcı ile her boyutta bellek boyutum çok büyüktü.
Stewart

@Stewart - Bunların çoğu karma değerinizin boyutuna bağlıdır. Benim durumumda, karma değer çıktısı int64 olarak sakladığım 64 bitlik tek bir alan. Çok daha büyük bir phash veri türünüz var gibi görünüyor. Aramaların böyle farklı bir veri türünde nasıl çalışacağından da emin değilim. Hâlâ metrik bir alan mı? Mesafeyi nasıl hesaplıyorsunuz?
Sahte İsim

Opencv ile sağlanan FLANN yürüyüşü ile 32bit tanımlayıcıları kullanıyorum. Mesafeyi hesaplamak için Lowe oranına göre bir eşik ile çekiçleme kullanıyorum. Bu noktada bir KD ağacı yapısı sağlayan FLANN bellek veya sopa ile denemek ve sizin için daha benzer bir çözüm geçmek için en iyi emin değilim. Neden kendi yuvarlanıp libflann gibi bir şeye gitmiyorsun?
Stewart

@Stewart - Ben kendim gelmedim. Süper sıkıcı DFT tabanlı karma kullanıyorum .
Sahte Ad

7

MOAR CEVAPLAR!

Tamam, sonunda özel bir PostgreSQL indeksleme uzantısı yazmak için zaman ayırdım. Kullandığım SP-GiST arayüz .

Bu oldukça zordu, çünkü Posgres büyüktü .

Her neyse, her zamanki gibi, burada github var .

Performans açısından, şu anda bu soruya verilen diğer cevabımda bellekte saf uygulamadan yaklaşık 2-3 kat daha yavaş, ama kullanmak çok daha uygun, bu performans vuruşunu mutlu bir şekilde yiyeceğim (gerçekçi olarak, ~ 50 ms / query - hala oldukça küçük olan 150 ms / query).


Müthişsin! Nasıl kuracağınıza bir README ekleyebilir misiniz? Postgres'te gerçekten hiçbir şey
kurmadım

1
@HypeWolf - Reponun kökünde bir README vardır . Bu istediğini kapsamıyor mu?
Sahte İsim

Benim hatam, onu görmedim, nereye baktığımdan emin değilim: /
HypeWolf

README de arıyordu. Kök klasörde. Bağlantı bir alt klasöre gidiyor. Bu kafa karıştırıcıydı.
luckydonald
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.