postgres의 빠른 해밍 거리 쿼리


15

지각 해시 이미지를 포함하는 큰 데이터베이스 (16M 행)가 있습니다.

합리적인 시간 내에 해밍 거리 로 행을 검색하고 싶습니다 .

현재 문제를 올바르게 이해하는 한 여기에서 가장 좋은 옵션은 BK-Tree 를 구현하는 사용자 지정 SP-GiST 구현 이라고 생각하지만 많은 작업처럼 보이며 여전히 실용적입니다. 맞춤 색인을 올바르게 구현하는 데 대한 세부 정보 해밍 거리를 계산하는 것은 다루기 쉬운 충분하다, 나는 할 수 있지만, C를 알고있다.

기본적으로 여기에 적절한 접근 방법은 무엇입니까? 해시의 특정 편집 거리 내에서 일치 항목을 쿼리 할 수 ​​있어야합니다. 내가 알고있는 것처럼, 같은 길이의 문자열 Levenshtein 거리가 기능적으로 거리를 해밍, 그래서 적어도이 몇 가지 내가 원하는에 대한 기존 지원은 (기억에서 명확한 방법은, 내가를 쿼리하고있어 값을 인덱스를 생성하지 않으려면하지만, 고정 값으로부터의 거리를 미리 계산할 수는 없습니다. 그 값은 해당 값에만 유용하기 때문입니다).

해시는 현재 해시의 이진 ASCII 인코딩 (예 : "10010101 ...")을 포함하는 64 자 문자열로 저장되지만 쉽게 int64로 변환 할 수 있습니다. 실제 문제는 상대적으로 빠른 쿼리가 가능해야한다는 것입니다.

내가 원하는 것의 선을 따라 무언가를 달성하는 것이 가능할 수있는 것처럼 보이지만 pg_trgmtrigram match mechamism이 어떻게 작동하는지 (특히, 반환되는 유사성 메트릭이 실제로 무엇을 나타내는 지) 약간 불분명합니다. 편집 거리와 같은 종류).

삽입 성능은 중요하지 않습니다 (각 행의 해시를 계산하는 데 계산 비용이 많이 듭니다). 나는 주로 검색에 관심이 있습니다.



@NeilMcGuigan-재미있는! 첫 번째 프레젠테이션은 실제로 postgres에서 SP-GiST 및 GIST 시스템을 유지 관리하는 사람들이 발표 한 것입니다.
— 가짜 이름

첫 번째 링크는 근본적으로 다른 것입니다. 그들은 교차점을 찾고 있지만 해밍 거리를 찾고 있습니다. 파시를 세트에 집어 넣을 수는 있지만 매우 지저분하고 다른 곳에서는 많은 지원 코드가 필요합니다.
— 가짜 이름

FWIW,이 시점에서 필자는 자체 인덱싱 시스템을 구현해야한다고 결론을 내 렸습니다. 나는 현재 맞춤 SP-GiST 지수를 조사하고 있지만, 내가 무엇을하고 있는지 전혀 모른다.
— 가짜 이름

1
@ 가짜 이름 : 해밍 거리를 말할 때 이미지가 아닌 해시 값 문자열의 해밍 거리를 의미한다고 가정합니다. 다시 말해, 당신은 묻고 자합니다 : 입력 매개 변수에서 X 비트로 대체되는 모든 해시 값을 찾으십시오
— Thomas Kejser

답변:


11

글쎄, 나는 사용자 정의 postgres C 확장을 작성하는 데 시간을 보냈고 BK 트리 구조를 메모리에 유지하는 Cython 데이터베이스 래퍼를 작성하는 것을 마무리했다.

기본적으로 데이터베이스에서 파시 값의 메모리 내 사본을 유지 관리하며 데이터베이스에 대한 모든 업데이트는 BK 트리로 재생됩니다.

여기 모두 github에 있습니다 . 또한 많은 단위 테스트가 있습니다.

거리가 4 인 항목에 대해 천만개의 해시 값 데이터 세트를 쿼리하면 트리 값의 ~ 0.25 % -0.5 %를 건드리고 ~ 100ms가 걸립니다.


메모리에 1600 만 개의 행이있는 메모리의 BK-Tree? 나는 메모리 크기가 큰 각 이미지에 1000 개의 이미지와 2000 개의 설명자가있는 비슷한 것을보고있었습니다.
— 스튜어트

@ 스튜어트-이것의 대부분은 해시의 크기에 달려 있습니다. 필자의 경우 해시 값 출력은 int64로 저장하는 단일 64 비트 비트 필드입니다. 훨씬 더 큰 파시 데이터 형식을 가진 것 같습니다. 또한 다른 데이터 유형에서 검색이 어떻게 작동하는지 잘 모르겠습니다. 그들은 여전히 ​​미터법 공간입니까? 거리는 어떻게 계산합니까?
— 가짜 이름

opencv와 함께 제공된 FLANN marcher와 함께 32 비트 설명자를 사용하고 있습니다. 거리를 계산하기 위해 Lowe의 비율에 따라 임계 값으로 해밍을 사용합니다. 이 시점에서 KD 트리 구조를 제공하거나 사용자와 더 유사한 솔루션으로 전환하는 메모리 FLANN을 사용하는 것이 가장 좋은지 잘 모르겠습니다. 왜 자신을 굴려서 libflann과 같은 것을 가지지 않았습니까?
— 스튜어트

@ 스튜어트-나는 내 자신을 굴리지 않았다. 슈퍼 보링 DFT 기반 해싱을 사용하고 있습니다.
— 가짜 이름

7

무어 대답!

좋아, 마침내 사용자 정의 PostgreSQL 인덱싱 확장을 작성하는 데 시간이 걸렸습니다. 내가 사용 SP-GIST 인터페이스를 .

이것은 대부분 Posgres가 크기 때문에 상당히 어려웠습니다 .

어쨌든 평소와 같이 github 여기 있습니다 .

성능 측면에서,이 질문에 대한 다른 대답에서 현재 메모리 내 구현보다 ~ 2 ~ 3 배 느리지 만 사용하는 것이 훨씬 편리합니다. 성능 히트를 행복하게 먹을 것입니다 (실제로 ~ 50입니다) ms / query-150ms / query, 여전히 작습니다).


당신은 굉장합니다! 설치 방법에 대한 README를 추가 할 수 있습니까? Postgres : P
— HypeWolf

1
@HypeWolf-저장소의 루트 에는 README가 있습니다. 그것은 당신이 원하는 것을 다루지 않습니까?
— 가짜 이름

내 실수, 나는 그것을 보지 못했다, 내가 어디에서 찾고 있는지 모르겠다 : /
— HypeWolf

README도 찾고있었습니다. 루트 폴더에 있습니다. 링크가 일부 하위 폴더로 연결됩니다. 혼란 스러웠습니다.
— luckydonald
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.