수백만 레코드에서 일치하는 부분 이름


10

이름 일치를위한 웹 기반 응용 프로그램을 개발했습니다. 이름을 여러 부분으로 나눠서 작동하며 각 부분 의 Soundex 값은 데이터베이스에 저장됩니다. Levenshtein 거리 메트릭은 특정 이름에 대해 백분율 사운드의 매칭뿐만 아니라, 스펠링을 적용하기 위해 사용된다.

런타임에 모든 레코드를 메모리에로드하고 Levenshtein 거리를 모든 Soundex 값과 모든 이름의 모든 부분의 철자에 적용합니다.

처음에는 최대 2,000 개의 이름이 있었기 때문에 처음에는 제대로 작동했지만 이제는 클라이언트 중 하나에 3 천만 개의 이름이 있습니다. 각 요청에 대해이 거대한 목록을 메모리에로드하고이 유형의 일치를 적용하는 것은 많은 메모리와 실행 시간을 사용하는 한심한 접근 방식입니다.

소리와 맞춤법의 백분율 일치를 통해 가까운 시일 내에 3000 만 건 이상의 레코드를 검색 할 수있는 제안을 찾고 있습니다.

핵심 기능

최종 사용자는 일치시킬 이름과 최소 백분율을 입력합니다. 우리는 이름의 어떤 부분이 주어진 이름의 어떤 부분과 주어진 백분율까지 일치하는 데이터베이스에 모든 이름을 보여 주어야합니다. 성명을 일치시킬 필요는 없습니다. 백분율까지 일치하면 성공합니다. 예를 들어.

Given Name: Helen Hunt
Name in DB: Holly Hunter 

두 이름의 두 부분이 정확히 일치하지는 않지만 어느 정도까지는 80 %로 가정하여 사용자가 80 %를 입력하면 DB의 이름이 일치하는 이름으로 표시되어야합니다.


1
SQL Server를 사용하고 있습니까? 나는 당신이 asp.net 태그를 참조하십시오. 네트워크 트래픽을 방지하고 SQL Server가 메모리를 관리하게 할 CLR 어셈블리의 가능성을 생각합니다.
RubberChickenLeader

@WindRaven 우리는 SQL Server와 Oracle을 모두 사용합니다
bjan

1
Google이 해결하는 것과 동일한 웹 크롤링 문제가 아닙니까?
candied_orange

@bjan 이름은 어디에 저장되어 있습니까? 그들은 SQL Server에 저장되어 있습니까?
RubberChickenLeader

무엇을 찾고 있습니까? 주어진 검색어와 가장 일치하는 상위 100 개의 이름은 무엇입니까?
Doc Brown

답변:


6

당신이 필요의 자세한 내용을 모른 채, 당신은 아마 다음 중 하나를 수행합니다 :

스핑크스 설치 및 구성과 관련된 내용을 완전히 알지 못합니다. 그러나 나는 데이터베이스에서 지적하고 색인을 생성 할 필드, 결과 가중치를 부여하는 방법을 알려주고 일치하는 레코드의 순서 목록을 제공합니다.

사용자가 직면하거나 미션 크리티컬 한 물건을 사용하려면 기존 검색 도구를 사용하십시오.

당신이 학업을 느끼고 있다면 ... ngrams와 함께 플레이 :

ngrams 조회 테이블은 잠재적 인 일치 항목의 초기 세트 역할을 할 수 있으며 Levenshtein 거리를 사용하여 결과를 정리하고 정렬 할 수 있습니다.

검색하고 싶다고 가정하면 people다음과 같이 할 수 있습니다.

_ people _________
personId: int
name: varchar
soundex_name: varchar

_ people_ngrams __
personId: int
ngramId: int

_ ngrams _________
ngramId: int
ngram: char(3)
count: int

ngram을 주기적으로 재 구축하거나 즉석에서 구축 할 수 있습니다. 어느 쪽이든 단순하고 순진한 검색 알고리즘은 다음과 같습니다.

search_ngrams = ngrammify(soundex(search_string));

notable_ngrams = select top 10 *
  from ngrams
  where ngram in (search_ngrams)
  order by count asc;

possible_matches = select top 1000 distinct people.*
  from people_ngrams, people
  where ngramId in (notable_ngrams);

best_matches = top 100 possible_matches
  ordered by Levenshtein_distance(match, soundex(search_string));

이와 비슷한 것을 사용 하지만 (ngram "인기"튜닝, 블랙리스트, 화이트리스트 등), 나는 이런 종류의 알고리즘이 데이터 세트 사이에서 레코드를 대량으로 병합하고 사용자 정의 퍼지 검색을 용이하게하는 것을 보았습니다. 유틸리티 및 지속적인 기록 중복 제거 노력.

이제 필자의 경우 수백만 개의 레코드와 일치하지 않았기 때문에 각 데이터 수십만 개의 레코드 순서로 두 데이터 세트간에 가능한 최상의 병합을 선택하려고했습니다. 그리고 몇 분 안에 상당히 빠르게 작동하기를 원했습니다. (빠른, 100,000 * 100,000은 무엇입니까?) 그리고 우리는 성공했습니다.

따라서 올바른 조정을 사용하면 이러한 종류의 작업이 매우 빠르고 효과적 일 수 있습니다. 우리는 궁극적으로 몇 분 안에 겸손하고 날짜가 적힌 듀얼 코어 머신에서 병합 된 세트를 생성 할 수 있었으며, 수동으로 검토 할 수 있도록 "질문이있는"병합이 자동으로 표시되었습니다. 그러나 ngram 인기 / 관련 스위트 스팟, 올바른 문자열 거리 임계 값, 블랙리스트 및 화이트리스트 등을 찾는 데 많은 시간이 걸렸습니다.

말했듯이 , 당신은 실제로이 물건들에서 일하는 구멍 에 빠질 수 있습니다. 실제 프로덕션 수준의 자료에는 일반적으로 이러한 종류의 검색에 맞게 이미 만들어 지고 최적화 된 잘 구축 된 도구를 사용해야합니다 .

스핑크스 또는 루신 처럼 .


방금 Sphinx 2.2.11 릴리스 참조 매뉴얼 에서 퍼지를 검색 했으며 단어를 부분적으로 일치시켜야하는 동안 정확한 단어와 일치하는 것으로 보입니다. 내가 틀렸다면 정정하십시오.
bjan

@bjan 그래. 문서를 더 자세히 살펴보면 스핑크스의 퍼지 검색이 정확히 무엇인지 확실하지 않습니다. soundex 형태를 사용할 수 있습니다 . 그러나 최근 편집 내용에 따라 자신의 ngram + string-distance 검색을 굴릴 수도 있습니다 . 위에서 말했듯이 알고리즘과 임계 값을 조정하려면 시간이 오래 걸릴 수 있습니다. 그러나 그것은 불가능하지 않습니다. 그리고 그 수준의 유연성이 필요하다면 ...
svidgen

@bjan 아, 나는 또한 Lucene 에 대해 완전히 잊었습니다 . 나는 그것이 당신이 필요로하는 것을 확실하지 않다; 그러나, 그것은 대담한 인기가 있으며, 자신을 굴리기 전에 살펴볼 가치가 있습니다. Lucene의 문서 에는 Levenshtein 문자열 거리를 사용한 퍼지 검색 및 순위가 언급되어 있습니다.
svidgen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.