Saya memiliki basis data besar (16M baris) yang berisi hash perceptual gambar.
Saya ingin dapat mencari baris dengan jarak tempuh dalam jangka waktu yang masuk akal.
Saat ini, sejauh yang saya mengerti benar masalah ini, saya pikir pilihan terbaik di sini adalah implementasi SP-GiST kustom yang mengimplementasikan BK-Tree , tapi itu sepertinya banyak pekerjaan, dan saya masih bingung pada praktis rincian penerapan indeks kustom dengan benar. Menghitung jarak Hamming cukup penurut, dan saya lakukan tahu C, meskipun.
Pada dasarnya, apa pendekatan yang tepat di sini? Saya harus dapat meminta kecocokan dalam jarak edit tertentu dari hash. Seperti yang saya pahami, jarak Levenshtein dengan string dengan panjang yang sama secara fungsional adalah jarak hamming, jadi setidaknya ada beberapa dukungan yang ada untuk apa yang saya inginkan, meskipun tidak ada cara yang jelas untuk membuat indeks dari itu (ingat, nilai yang saya minta untuk perubahan. Saya tidak dapat melakukan pra-hitung jarak dari nilai tetap, karena itu hanya akan berguna untuk nilai yang satu itu).
Hash saat ini disimpan sebagai string 64-char yang berisi pengkodean ASCII biner dari hash (misalnya "10010101 ..."), tetapi saya dapat mengonversinya menjadi int64 dengan cukup mudah. Masalah sebenarnya adalah saya harus bisa melakukan query relatif cepat.
Sepertinya itu mungkin untuk mencapai sesuatu di sepanjang garis yang saya inginkan dengan pg_trgm
, tapi saya agak tidak jelas tentang bagaimana mekanisme pencocokan trigram bekerja (khususnya, apa kesamaan metrik yang dikembalikan sebenarnya mewakili? Tampaknya jenis seperti edit-jarak).
Memasukkan kinerja tidak penting (sangat mahal secara komputasi untuk menghitung hash untuk setiap baris), jadi saya terutama peduli tentang pencarian.
sumber
Jawaban:
Yah, saya menghabiskan waktu melihat penulisan ekstensi postgres C kustom, dan akhirnya hanya membungkus pembungkus basis data Cython yang mempertahankan struktur pohon-BK dalam memori.
Pada dasarnya, ia memelihara salinan dalam memori dari nilai-nilai phash dari database, dan semua pembaruan ke database diputar ulang ke pohon-BK.
Semuanya ada di github di sini . Ini juga memiliki BANYAK unit-tes.
Meminta set data 10 juta nilai hash untuk item dengan jarak 4 hasil menyentuh ~ 0,25% -0,5% dari nilai di pohon, dan membutuhkan ~ 100 ms.
sumber
JAWABAN MOAR!
Oke, saya akhirnya meluangkan waktu untuk menulis ekstensi pengindeksan PostgreSQL khusus. Saya menggunakan antarmuka SP-GiST .
Ini cukup menantang, terutama karena Posgres besar .
Bagaimanapun, seperti biasa, ada di github di sini .
Dari segi kinerja, saat ini ~ 2-3 kali lebih lambat daripada implementasi murni-dalam-memori dalam jawaban saya yang lain untuk pertanyaan ini, tetapi jauh lebih nyaman untuk digunakan. Saya akan dengan senang hati memakan kinerja yang memukul (secara realistis, itu ~ 50 ms / query - 150 ms / query, yang masih cukup kecil).
sumber