다음과 같은 문제가 있습니다. 2 백만 개 이상의 레코드가 포함 된 데이터베이스가 있습니다. 각 레코드에는 문자열 필드 X가 있으며 필드 X에 특정 문자열이 포함 된 레코드 목록을 표시하려고합니다. 각 레코드의 크기는 약 500 바이트입니다.
좀 더 구체적으로 : 응용 프로그램의 GUI에는 문자열을 입력 할 수있는 텍스트 필드가 있습니다. 텍스트 필드 위에 텍스트 필드의 문자열과 일치하는 (첫 번째 N, 예를 들어 100) 레코드를 표시하는 테이블이 있습니다. 텍스트 필드에 문자를 입력하거나 삭제할 때 테이블 내용을 즉시 업데이트해야합니다.
적절한 인덱스 구조 및 / 또는 캐싱을 사용 하여이 작업을 수행하는 효율적인 방법이 있는지 궁금합니다. 위에서 설명한 것처럼 쿼리와 일치하는 첫 번째 N 항목 만 표시하고 싶습니다. 따라서 N의 크기가 작 으면 데이터베이스에서 일치하는 항목을로드하는 데 큰 문제가되지 않습니다. 또한 주 메모리에 항목을 캐시하면 검색 속도가 빨라질 수 있습니다.
주요 문제는 패턴 문자열을 고려하여 일치하는 항목을 빨리 찾는 방법입니다. 일부 DBMS 기능에 의존 할 수 있습니까? 아니면 인 메모리 인덱스를 직접 만들어야합니까? 어떤 아이디어?
편집하다
첫 번째 실험을 진행했습니다. 레코드를 다른 텍스트 파일로 분할하고 (파일 당 최대 200 개의 레코드) 파일을 다른 디렉토리에 넣었습니다 (한 데이터 필드의 내용을 사용하여 디렉토리 트리를 결정했습니다). 약 40000 개의 디렉토리에 약 50000 개의 파일이 있습니다. 그런 다음 Lucene을 실행하여 파일을 색인화했습니다. Lucene 데모 프로그램으로 문자열을 검색하는 것은 매우 빠릅니다. 분할 및 인덱싱에는 몇 분이 걸렸습니다. 쿼리하려는 정적 데이터 세트이기 때문에 이것은 전적으로 허용됩니다.
다음 단계는 Lucene을 기본 프로그램에 통합하고 Lucene이 리턴 한 적중을 사용하여 관련 레코드를 기본 메모리에로드하는 것입니다.
답변
DB에 데이터를 저장하는 대신이를 일련의 문서 (텍스트 파일)로 유지하고 링크 (경로 / URL 등)를 DB에 유지할 수 있습니다.
이는 디자인에 의한 SQL 쿼리가 하위 문자열 검색과 검색 모두에서 매우 느리기 때문에 필수적입니다.
이제 문제는 문자열 집합이 포함 된 텍스트 파일을 검색해야하는 것으로 공식화되었습니다. 여기에는 두 가지 가능성이 있습니다.
-
하위 문자열 일치 텍스트 얼룩이 단일 스팅 또는 단어 (공백 없음)이고 임의의 하위 문자열을 검색해야하는 경우. 이러한 경우 일치하는 최상의 파일을 찾기 위해 모든 파일을 구문 분석해야합니다. 하나는 Boyer Moor 알고리즘과 같은 알고리즘을 사용합니다. 만나다 이 와 이 내용은. grep은 grep과 비슷합니다. grep은 비슷한 것을 내부에서 사용하기 때문입니다. 그러나 귀국하기 전에 여전히 최소 100 + grep (최악의 경우 2 백만)을 만들 수 있습니다.
-
인덱스 검색. 여기서 텍스트에 단어 세트가 포함되어 있고 검색이 고정 단어 길이로 제한되어 있다고 가정합니다. 이 경우 문서는 가능한 모든 단어에 대해 색인됩니다. 이것을 “전체 텍스트 검색”이라고합니다. 이를 수행하기위한 많은 알고리즘과 직접 사용할 수있는 오픈 소스 프로젝트가 있습니다. 이들 중 다수는 아래와 같이 와일드 카드 검색, 근사 검색 등을 지원
합니다. Apache Lucene : http://lucene.apache.org/java/docs/index.html
b. OpenFTS : http://openfts.sourceforge.net/
c. 스핑크스 http://sphinxsearch.com/
쿼리로 “고정 단어”가 필요한 경우, 두 번째 방법은 매우 빠르고 효과적입니다.
답변
찾고있는 기술은 전체 텍스트 인덱싱입니다. 대부분의 RDBMS에는 여기에서 작동하는 일종의 내장 기능이 있거나, 더 좋아지고 메모리에서 실행하려는 경우 Lucene과 같은 것을 사용할 수 있습니다.
답변
당신은 트라이 를 고려 했습니까 ? 기본적으로 공통 접두사를 사용하여 트리를 작성하므로 동일한 문자로 시작하는 모든 단어는 동일한 노드의 자식입니다. 하위 문자열에서 일치하는 것을 지원하려면 일종의 순열 인덱스 를 생성하고 그로부터 trie를 작성해야합니다. 그래도 스토리지 요구 사항이 사라질 수 있습니다.
답변
Wyatt Barnett의 답변에 추가하여 적절한 열에 전체 텍스트 인덱싱을 사용하는 RDBMS 솔루션이 작동하지만 이전에 가져온 레코드의 로컬 캐시를 사용하려면 이러한 캐시 된 레코드를 활용할 계획이 필요합니다 당신의 이점에.
한 가지 옵션은 쿼리에서 명시 적으로 검색하지 않으려는 이러한 레코드의 고유 식별자를 수집하여 가능한 경우 a NOT IN
또는 a에 포함시키는 것 NOT EXISTS
입니다.
그러나주의 NOT IN
하거나 사용 NOT EXISTS
하는 것이 저렴하지는 않으며 사용중인 데이터베이스 엔진에 따라 쿼리 성능 또는 쿼리 계획에 부정적인 영향을 줄 수 있습니다. 최종 쿼리에서 Explain Plan을 실행하여 영향을받는 열의 모든 인덱스가 사용되도록하십시오.
또한 두 가지 방법 중 성능 비교를 수행하여 어느 것이 더 빠른지 아프지 않습니다. 로컬 캐시를 유지 관리하고 쿼리에서 캐시를 명시 적으로 필터링하면 모든 레코드를 가져 오는 미세 조정 된 쿼리보다 성능이 저하 될 수 있습니다.
답변
당신이 그것을 놓친 경우를 대비하여. DB 내 지원 텍스트 검색 대신 데이터베이스에 Lucene을 사용하는 경우 DB를 수정할 때 매우주의해야합니다. DB와 외부 리소스 (Lucene)를 모두 변경해야 할 때 원 자성을 가질 수있는 방법은 무엇입니까? 그렇습니다, 그러나 많은 일이있을 것입니다.
간단히 말해 Lucene을 데이터 스키마에 넣으면 DB 트랜잭션 지원이 손실됩니다.
답변
스핑크스를 고려 했습니까? http://sphinxsearch.com 타사 도구를 사용할 수 있다면 이것이 달성하려는 목표에 이상적입니다. 개인적으로 사용한 RDBMS보다 전체 텍스트 검색에서 훨씬 더 효율적입니다.
답변
어떤 답변도 Apache Lucene 및 기타 솔루션과 유사한 모든 솔루션의 기초가되는 기술인 “inverted index” 라는 용어를 제시하지 않은 것은 다소 이상합니다 .
반전 된 색인은 단어에서 문서로의 매핑 ( “레코드 수준 반전 된 색인”) 또는 문서 내의 정확한 단어 위치 ( “워드 수준의 반전 된 색인”)입니다.
AND 및 OR 논리 연산은 구현하기가 쉽지 않습니다. 정확한 단어 위치가 있으면 인접한 단어를 찾아 구문 검색을 수행 할 수 있습니다.
따라서 (단어, 파일, 위치) 튜플을 포함하는 색인에 대해 생각하십시오. 예를 들어 ( “inverted”, “foo.txt”, 123)가있는 경우 ( “index”, “foo.txt”, 124)가 “inverted index”라는 구절을 검색하기위한 인덱스의 일부인지 확인하면됩니다. .
전체 텍스트 검색 엔진을 처음부터 다시 구현하는 것은 좋지 않지만 Apache Lucene과 같은 기술의 작동 방식을 아는 것이 유용합니다.
따라서 역 인덱스가 어떻게 작동하는지 배우고 Apache Lucene과 같은 인덱스를 사용하는 기술을 선택하는 것이 좋습니다. 그런 다음에는 수행 할 수있는 작업과 수행 할 수없는 작업에 대해 확실하게 이해해야합니다.