티스토리 뷰

Lucene에서 색인을 하는 과정

우선 lucene에서는 크게 다음과 같은 과정으로 색인을 하게 됩니다.

 

Lucene에서는 Index File을 생성할 때, Index File Format인 Segment File을 통해 색인을 하며, Segment File이 생성되면, DocumentWriter를 통해 색인하는 과정이 만들어지고 색인이 완료되면, Commit을 통해 실제 데이터 파일에 쓰입니다. 하나의 Index에는 여러 개의 Segment File이 존재하는데, 여러 개의 Segment File이 Commit이 되면, SegmentMerger를 통해 merge 작업을 수행하는 흐름으로 색인을 하게 됩니다.

 

여기서 여러 개의 Segment File이 존재하는 이유가 궁금하실 수도 있는데요. 색인이 된 Index File(Segment File)들은 수정이 불가능한 Immutable Type이기 때문에 하나의 Index File(Segment File)이 생성되면, 수정이나 삭제가 되지 않습니다. 따라서 변경이 필요하면, 또 다른 Index File(Segment File)들을 생성해야 합니다. 이렇기 때문에 Segment File이 여러 개가 존재하며, 여러 개의 Segment File들을 Merge 해주는 작업이 필요하게 됩니다.

Segment File 이란?

여러 Index File의 유형 중 하나이며, segments_N 확장자를 사용하고 있습니다. 주로 Commit Point에 대한 정보를 저장하고 있습니다. Segment File에 대해 자세하게 알고 싶다면, 해당 링크를 통해 정보를 얻을 수 있습니다.

 

org.apache.lucene.codecs.lucene87 (Lucene 8.10.1 API)

Package org.apache.lucene.codecs.lucene87 Description Lucene 8.7 file format. Apache Lucene - Index File Formats Introduction This document defines the index file formats used in this version of Lucene. If you are using a different version of Lucene, pleas

lucene.apache.org

실제로 어떻게 처리되는지 확인

실제로 어떻게 처리되는지 확인하기 위해서 lucene 프로젝트를 clone 하고, TestIndexWriter.java에 있는 testDocCount() 테스트 메서드를 통해 확인할 수 있었습니다.

 

GitHub - apache/lucene: Apache Lucene open-source search software

Apache Lucene open-source search software. Contribute to apache/lucene development by creating an account on GitHub.

github.com

  public void testDocCount() throws IOException {
    Directory dir = newDirectory();

    IndexWriter writer = null;
    IndexReader reader = null;
    int i;

    // IndexWriter 클래스를 생성해서, 하나의 Segment 파일을 만든다.
    writer = new IndexWriter(dir, newIndexWriterConfig(new MockAnalyzer(random())));

    // 100개의 documents 추가하여 색인한 후, Commit을 한다.
    for (i = 0; i < 100; i++) {
      addDocWithIndex(writer, i);
      if (random().nextBoolean()) {
        writer.commit();
      }
    }
    
    // 현재 Documents의 상태
    IndexWriter.DocStats docStats = writer.getDocStats();
    assertEquals(100, docStats.maxDoc);
    assertEquals(100, docStats.numDocs);
    writer.close();

    // 새로운 IndexWriter 클래스를 생성해서, 또 다른 Segment 파일을 만든다.
    writer =
        new IndexWriter(
            dir,
            newIndexWriterConfig(new MockAnalyzer(random()))
                .setMergePolicy(
                    new FilterMergePolicy(NoMergePolicy.INSTANCE) {
                      @Override
                      public boolean keepFullyDeletedSegment(
                          IOSupplier<CodecReader> readerIOSupplier) {
                        return true;
                      }
                    }));

    // 40개의 Documents를 삭제하여 색인한 후, Commit을 한다.
    for (i = 0; i < 40; i++) {
      writer.deleteDocuments(new Term("id", "" + i));
      if (random().nextBoolean()) {
        writer.commit();
      }
    }
    
    // flush()를 통해 2개 Commit에 대한 Merge를 수행한다.
    // IndexWriter.flush() -> IndexWriter.maybeMerge() -> IndexWriter.executeMerge() 
    // -> MergeScheduler.merge(mergeSoruce) -> MergeSource.merge() 
    // -> IndexWriter.merge() -> IndexWriter.mergeMiddle() 메소드 안에 SegmentMerger 클래스가 merge를 진행한다.
    writer.flush();
    
    // 현재 Documents 상태
    docStats = writer.getDocStats();
    assertEquals(100, docStats.maxDoc);
    assertEquals(60, docStats.numDocs);
    writer.close();
}

하나의 IndexWriter를 통해 Segment File을 생성하고, 100개의 Documents를 추가하여 색인한 후, Commit을 통해 실제 데이터 파일에 쓰이게 됩니다. 이 때 새로운 IndexWriter를 통해 Segment File을 생성하게 되면, 현재 2개의 Segment File이 존재하게 됩니다. 새롭게 생성된 Segment File에는 40개의 Documents를 삭제하여 색인을 하고, Commit을 통해 실제 데이터 파일에 쓰여지게 됩니다. 마지막에 writer.flush() 메서드를 통해 SegmentMerger 클래스에 의해서 2개 Segment에 대한 Commit은 Merge 됩니다.

 

writer.flush() 메서드의 흐름은 다음과 같이 동작하게 되는데요. indexWriter.flush() -> indexWriter.maybeMerge() -> indexWriter.executeMerge() -> MergeScheduler.merge(MergeSource mergeSource, MergeTrigger trigger) -> MergeSource.merge() -> IndexWriter.merge() -> IndexWriter.mergeMiddle() 흐름으로 동작하게 됩니다. 이때, IndexWriter.mergeMiddle()에서 SegmentMerger 클래스를 생성한 후, 실제 2개 Segment에 대한 Commit 정보를 Merge 합니다.

참고

https://lucene.apache.org/core/8_10_1/core/org/apache/lucene/codecs/lucene87/package-summary.html#package.description

 

org.apache.lucene.codecs.lucene87 (Lucene 8.10.1 API)

Package org.apache.lucene.codecs.lucene87 Description Lucene 8.7 file format. Apache Lucene - Index File Formats Introduction This document defines the index file formats used in this version of Lucene. If you are using a different version of Lucene, pleas

lucene.apache.org

https://github.com/apache/lucene

 

GitHub - apache/lucene: Apache Lucene open-source search software

Apache Lucene open-source search software. Contribute to apache/lucene development by creating an account on GitHub.

github.com

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함