반응형

https://www.alibabacloud.com/blog/analysis-of-lucene---basic-concepts_594672 

 

Analysis of Lucene - Basic Concepts

This article mainly deals with some of Lucene's basic concepts and the index types supported.

www.alibabacloud.com

 

Apache Lucene은 강력한 데이터 검색 기능을 갖춘 확장 가능한 고성능 오픈 소스 데이터 검색 엔진입니다. Lucene은 수년에 걸쳐 개발되어 더 강력한 기능과 점점 더 세련된 아키텍처를 제공합니다. 현재 전체 텍스트 인덱싱을 지원하고 다양한 유형의 쿼리 요구 사항을 충족하기 위해 다른 많은 유형의 인덱싱을 제공합니다.

많은 오픈 소스 프로젝트는 Lucene을 기반으로 합니다. 가장 잘 알려진 것은 Elasticsearch와 Solr입니다. Elasticsearch와 Solr를 정교하게 설계된 고성능 스포츠카에 비유한다면 Lucene은 강력한 원동력을 제공하는 엔진일 것입니다. 더 빠르고 안정적인 승차감을 제공하기 위해 자동차를 튜닝하려면 엔진을 세세하게 연구해야 합니다.

이전에 Elasticsearch의 데이터 모델, 읽기/쓰기 경로, 분산 아키텍처 및 데이터/메타 일관성을 분석하는 이 칼럼에 많은 기사를 게시했습니다. 이 기사 이후에 Lucene의 데이터 모델 및 데이터 읽기/쓰기 경로에 대한 완전한 분석을 제공하기 위해 Lucene 및 해당 소스 코드의 원리에 대한 일련의 기사를 계획합니다.

Lucene은 공식적으로 다음과 같은 이점을 요약합니다.

확장 가능한 고성능 인덱싱
강력하고 정확하며 효율적인 검색 알고리즘
이 기사 시리즈를 통해 독자들이 Lucene이 이러한 목표를 달성하는 방법을 이해할 수 있기를 바랍니다.

전체 분석은 Lucene 7.2.1을 기반으로 합니다. 이 기사를 읽기 전에 기본 검색 및 색인 원칙, 반전 색인과 같은 개념, 토큰화 및 관련성에 대한 이해와 Lucene의 기본 사용(예: Directory, IndexWriter 및 IndexSearcher)에 대한 이해를 포함하여 약간의 배경 지식이 필요합니다.

기본 개념
Lucene에 대해 자세히 알아보기 전에 몇 가지 기본 개념과 이러한 개념 뒤에 숨겨진 몇 가지 측면을 아는 것이 좋습니다.

1

그림은 인덱스의 기본 내부 구조를 보여줍니다. 세그먼트의 데이터는 실제 데이터 구조의 실제 표현이 아니라 추상적으로 표현됩니다.

색인
이것은 개념적으로 데이터베이스 테이블과 유사하지만 몇 가지 중요한 면에서 다릅니다. 전통적인 관계형 데이터베이스나 NoSQL 데이터베이스의 테이블은 생성될 때 적어도 스키마가 정의되어 있어야 합니다. 기본 키, 열 등의 정의에는 몇 가지 명확한 제약 조건이 있습니다. 그러나 Lucene 인덱스에는 이러한 제약이 없습니다. Lucene 인덱스는 문서 폴더로 이해할 수 있습니다. 새 문서를 폴더에 넣거나 빼면 되지만 문서 중 하나를 수정하려면 먼저 꺼내서 수정한 다음 다시 폴더에 넣어야 합니다. 모든 종류의 문서를 폴더에 넣을 수 있으며 Lucene은 내용이 무엇이든 문서를 인덱싱할 수 있습니다.

문서
관계형 데이터베이스의 행 또는 문서 데이터베이스의 문서와 유사하게 인덱스는 여러 문서를 포함할 수 있습니다. 색인에 기록된 문서에는 고유 ID, 즉 시퀀스 번호(일반적으로 DocId라고 함)가 할당됩니다. 시퀀스 번호는 나중에 자세히 설명합니다.

필드
하나의 문서는 하나 이상의 필드로 구성됩니다. 필드는 Lucene에서 정의할 수 있는 데이터 인덱스의 가장 작은 단위입니다. Lucene은 StringField, TextField 및 NumericDocValuesField를 포함하여 다양한 유형의 필드를 제공합니다. Lucene은 필드 유형(FieldType)에 따라 데이터에 사용할 인덱싱 유형(Invert Index, Store Field, DocValues 또는 N-dimensional)을 결정합니다. Field 및 FieldType에 대해서는 나중에 자세히 설명합니다.

용어 및 용어 사전
Lucene에서 가장 작은 색인 및 검색 단위입니다. 필드는 하나 이상의 용어로 구성됩니다. 분석기(토큰나이저)를 통해 필드를 넣으면 용어가 생성됩니다. 용어 사전은 용어에 대한 조건부 검색을 수행하는 데 사용되는 기본 색인입니다.

분절
인덱스는 하나 이상의 하위 인덱스로 구성됩니다. 하위 인덱스를 세그먼트라고 합니다. Lucene에서 세그먼트의 개념적 설계는 LSM과 유사하지만 몇 가지 차이점이 있습니다. LSM의 데이터 쓰기 이점을 상속하지만 실시간 쿼리가 아닌 거의 실시간으로만 제공합니다.

Lucene이 데이터를 쓸 때 먼저 메모리 내 버퍼에 씁니다(LSM의 MemTable과 유사하지만 읽을 수 없음). Buffer의 데이터가 일정량에 도달하면 플러시되어 Segment가 됩니다. 모든 세그먼트는 고유한 인덱스를 가지며 독립적으로 검색할 수 있지만 데이터는 절대 변경할 수 없습니다. 이 체계는 임의 쓰기를 방지합니다. 데이터는 Batch 또는 Append로 기록되며 높은 처리량을 달성합니다. Segment에 작성된 문서는 수정할 수 없지만 삭제할 수는 있습니다. 삭제 방법은 원래 내부 위치의 파일을 변경하지 않지만 삭제할 문서의 DocID를 다른 파일에 저장하여 데이터 파일을 수정할 수 없도록 합니다. 인덱스 쿼리는 여러 세그먼트를 쿼리하고 결과를 병합하고 삭제된 문서를 처리해야 합니다. Lucene에는 여러 세그먼트를 병합하는 정책이 있으며 이와 관련하여 LSM의 SSTable 병합과 유사합니다.

세그먼트가 플러시되거나 커밋되기 전에 데이터는 메모리에 저장되며 검색할 수 없습니다. 이것은 Lucene이 실시간 쿼리가 아닌 거의 실시간으로 제공한다고 말하는 또 다른 이유입니다. 코드를 읽은 후 검색 가능한 데이터 쓰기를 구현하지 못하는 것이 아니라 구현하기가 복잡하다는 것을 알았습니다. 그 이유는 Lucene에서 데이터 검색이 인덱스 설정에 의존하고(예: 역 인덱스는 용어 사전에 의존) Lucene의 데이터 인덱스는 실시간이 아닌 세그먼트 플러시 중에 설정되기 때문입니다. 이것의 목적은 가장 효율적인 인덱스를 설정하는 것입니다. 당연히 인덱스를 작성하면서 실시간으로 인덱스를 설정하는 또 다른 인덱스 메커니즘을 도입할 수 있지만 이러한 메커니즘의 구현은 세그먼트의 현재 인덱스와 다르기 때문에 쓰기 시간에 추가 인덱스를 도입하고 어느 정도의 복잡성을 포함하는 추가 쿼리 메커니즘.

시퀀스 번호
시퀀스 번호(이하 DocId라고 함)는 Lucene에서 중요한 개념입니다. 데이터베이스는 기본 키를 사용하여 행을 고유하게 식별하는 반면 Lucene의 인덱스는 DocId로 Doc를 고유하게 식별합니다. 그러나 다음 사항을 염두에 두어야 합니다.

DocId는 실제로 인덱스에 대해 고유하지 않지만 세그먼트에 대해 고유합니다. Lucene은 주로 쓰기 및 압축을 최적화하기 위해 이 작업을 수행합니다. 문서는 세그먼트에만 고유하므로 색인 수준에서 어떻게 문서를 고유하게 식별할 수 있습니까? 해결책은 간단합니다. 세그먼트가 정렬됩니다. 간단한 예를 들자면 인덱스에는 두 개의 세그먼트가 있고 각 세그먼트에는 각각 100개의 문서가 있습니다. 세그먼트의 DocId는 0-100이지만 인덱스 수준으로 변환될 때 두 번째 세그먼트의 DocId 범위는 100-200으로 변환됩니다.
DocId는 세그먼트 내에서 고유하며 0부터 점진적으로 번호가 매겨집니다. 그러나 이것이 DocId가 연속적이라는 의미는 아닙니다. 문서가 삭제되면 공백이 생깁니다.
문서에 해당하는 DocId는 일반적으로 세그먼트가 병합될 때 변경될 수 있습니다.
Lucene의 핵심인 역색인은 본질적으로 각 용어를 해당 용어를 포함하는 문서의 DocId에 매핑하는 목록입니다. 따라서 Lucene이 내부적으로 검색할 때 2단계 쿼리를 만듭니다. 첫 번째 단계는 주어진 Term을 포함하는 DocId를 나열하고 두 번째 단계는 DocId를 기반으로 Doc을 찾는 것입니다. Lucene은 DocId를 기반으로 쿼리할 뿐만 아니라 Term으로 검색하는 기능을 제공합니다.

DocId는 기본적으로 0부터 시작하는 int32 값이며 이는 중요한 최적화이며 데이터 압축 및 쿼리 효율성에도 반영됩니다. 여기에는 데이터 압축을 위한 델타 정책, ZigZag 코드 및 반전된 인덱스 목록에 사용되는 SkipList와 같은 최적화가 포함됩니다. 이에 대해서는 나중에 자세히 설명합니다.

인덱스 유형
Lucene은 많은 유형의 필드를 지원하며 각 유형의 필드는 지원되는 데이터 유형과 인덱스 모드를 결정합니다. 현재 지원되는 필드 유형에는 LongPoint, TextField, StringField 및 NumericDocValuesField가 있습니다.

2

그림은 Lucene의 다양한 유형의 필드 간의 기본 관계를 보여줍니다. 모든 Field 유형은 Field 클래스에서 상속됩니다. Field에는 name(String), fieldsData(BytesRef) 및 type(FieldType)의 세 가지 주요 특성이 있습니다. 속성 이름은 필드 이름이고 fieldsData는 필드 값입니다. 모든 유형의 필드 값은 궁극적으로 이진 바이트 스트림으로 표현됩니다. 속성 유형은 필드가 인덱싱되는 방식을 결정하는 필드 유형입니다.

FieldType은 많은 중요한 속성을 포함하는 중요한 클래스입니다. 이러한 속성의 값은 필드가 인덱싱되는 방식을 결정합니다.

Lucene은 다양한 유형의 필드를 제공합니다. 두 가지 중요한 차이점이 있습니다. 첫 번째 차이점은 fieldData의 다른 유형 값이 다른 변환 방법을 정의한다는 것입니다. 두 번째는 FieldType의 서로 다른 속성에서 서로 다른 값의 조합을 정의하는 것입니다. 이 모드에서는 사용자 정의 데이터를 사용하고 FieldType에서 색인 매개변수를 결합하여 유형을 사용자 정의할 수 있습니다.

Lucene이 제공할 수 있는 인덱스 모드를 알기 위해서는 FieldType의 각 속성에 대한 특정 의미를 이해하기만 하면 됩니다. 하나씩 살펴보겠습니다.

stored: 필드를 저장할지 여부를 나타냅니다. false인 경우 Lucene은 필드 값을 저장하지 않으며 쿼리 결과에 반환된 문서에는 저장된 필드만 포함됩니다.
tokenized: 토큰화 여부를 나타냅니다. Lucene에서는 TextField 필드만 토큰화하면 됩니다.
termVector: 이 글은 term vector의 개념을 잘 설명하고 있습니다. 간단히 말해서 용어 벡터는 용어 값, 빈도, 위치를 포함하여 용어와 관련된 모든 정보를 저장합니다. 문서별 역색인으로 문서 내 모든 용어 정보를 docid에 따라 찾을 수 있는 기능을 제공합니다. 다시 한 번 토큰화하면 모든 용어 정보를 얻을 수 있으므로 짧은 필드에 대해 용어 벡터를 활성화하지 않는 것이 좋습니다.그러나 더 긴 필드나 토큰화 비용이 높은 필드에 대해서는 용어 벡터를 활성화하는 것이 좋습니다. 용어 벡터에는 두 가지 주요 용도가 있습니다. 첫 번째는 키워드 강조 표시이고 다른 하나는 문서 간의 유사성 일치입니다(more-like-this).
omitNorms: Norms는 정규화를 나타냅니다. Lucene을 사용하면 모든 문서의 모든 필드에 정규화 요소(검색 중 점수 매기기와 관련된 계수)를 저장할 수 있습니다. Norms를 저장하는 데는 1바이트만 필요하지만 모든 문서의 모든 필드에 별도의 Norms가 저장되고 모든 Norms 데이터가 메모리에 로드됩니다. 따라서 Norms를 활성화하면 추가 저장 공간과 메모리가 소비됩니다. 그러나 Norms를 비활성화하면 인덱스 시간 부스팅(elasticsearch는 공식적으로 쿼리 시간 부스팅을 대신 사용하도록 권장함)과 길이 정규화를 사용할 수 없습니다.
indexOptions: Lucene은 역 인덱스(NONE, DOCS, DOCS_AND_FREQS, DOCS_AND_FREQS_AND_POSITIONS, DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS)에 대해 5개의 선택적 매개변수를 제공하며, 필드를 인덱싱해야 하는지 여부와 인덱싱할 콘텐츠를 선택하는 데 사용됩니다.
docValuesType: DocValue는 Lucene 4.0(docid to field 열 저장소)에 도입된 정방향 인덱스로 정렬, 패싯 및 집계의 효율성을 크게 향상시킵니다. DocValues는 강력한 스키마가 있는 저장소 구조이므로 DocValues가 활성화된 모든 필드의 유형은 정확히 동일해야 합니다. 현재 Lucene은 NUMERIC, BINARY, SORTED, SORTED_NUMERIC 및 SORTED_SET의 다섯 가지 유형만 제공합니다.
차원: Lucene은 다차원 데이터의 쿼리를 최적화하기 위해 특수 인덱싱을 사용하여 다차원 데이터의 인덱싱을 지원합니다. 이러한 유형의 데이터의 가장 일반적인 사용 시나리오는 지리적 위치의 인덱스입니다. 위도 및 경도 데이터에 일반적으로 사용되는 인덱싱 방법입니다.
Lucene에서 StringField를 정의하는 방법을 살펴보겠습니다.

3

StringField는 TYPE_NOT_STORED 및 TYPE_STORED라는 두 가지 유형의 인덱스를 정의합니다. 유일한 차이점은 필드를 저장해야 하는지 여부입니다. StringField에 대해 생략Norms를 선택한 경우 토큰화 없이 역인덱싱이 필요하다는 것은 다른 속성에서 해석할 수 있습니다.

Elasticsearch 데이터 유형
Elasticsearch에서 사용자가 입력한 문서 내 필드의 인덱싱 모드도 Lucene의 인덱싱 모드에 따라 제공됩니다. Elasticsearch에는 사용자 정의 필드 외에도 특정 특수 목적을 위한 자체 예약 시스템 필드가 있습니다. 이러한 필드는 사실상 Lucene의 필드에 매핑되며 사용자 정의 필드와 동일합니다. 그러나 이러한 시스템 필드의 목적에 따라 Elasticsearch에서 다양한 인덱싱 방법이 공식화되었습니다.

4

예를 들어 앞의 그림은 Elasticsearch에 있는 두 시스템 필드의 FieldType _version 및 _uid 정의를 보여줍니다. 인덱싱 방법을 해독해 봅시다. Elasticsearch는 _uid 필드로 문서를 고유하게 식별하고 _version 필드로 문서의 현재 버전을 기록합니다. 이 두 필드의 FieldType 정의에서 _uid 필드가 역 인덱스로 인덱싱되고 토큰화가 필요하지 않으며 저장되어야 함을 알 수 있습니다. _version 필드는 역 인덱스에 의해 인덱싱될 필요가 없으며, 저장이 필요하지 않지만 정방향 인덱싱이 필요합니다. _uid는 검색해야 하지만 _version은 검색하지 않기 때문에 이해하기 쉽습니다. 그러나 _version은 docId로 쿼리해야 하는 반면 Elasticsearch의 versionMap은 docId로 많은 수의 쿼리를 수행해야 하지만 _version 필드만 쿼리하면 됩니다. 정방향 인덱싱에 가장 적합한 _version을 만듭니다.

Elasticsearch의 시스템 필드에 대한 전체 분석은 다음 문서를 참조하십시오.

요약
이 문서는 주로 Lucene의 기본 개념과 지원되는 인덱스 유형 중 일부를 다룹니다. 우리는 Lucene의 일부인 IndexWriter가 쓰는 방법, 메모리 내 버퍼의 구조 및 일단 영구적인 인덱스 파일의 구조를 분석하여 Lucene이 어떻게 이러한 고효율 데이터 인덱싱을 달성하는지 이해하기 위한 일련의 향후 기사를 계획하고 있습니다. 또한 Lucene이 매우 효율적인 검색 및 쿼리를 제공하는 이유를 알아보기 위해 쿼리를 최적화하기 위한 일부 특수 데이터 구조와 함께 IndexSearcher의 쿼리 프로세스를 살펴볼 것입니다.

 

 

 

 

 

반응형

+ Recent posts