[강좌]Lucene Index File Format-1


Lucene Index File Format Overview에 이어 오늘은 하나의 인덱스에 한개나 두개정도 필수적으로 필요한 파일에 대한 설명을 하겠다.
물론 오늘의 백미는 세그먼트 병합(segment merge)이다.

4. 인덱스 파일당 포함되어 있는 것들

1)세그먼트(Segments) 파일
그 해당 인덱스에 포함되어 있는 세그먼트들에 대한 정보를 가지고 있는 파일이다. 오직 이 파일하나만 인덱스 파일에 포함되어 있으며 “segments”라는 파일명으로 존재한다. 이 리스트는 각 세그먼트를 이름으로 리스팅하고 또한 각 세그먼트의 크기도 명시하고 있다.
자세한건 아래를 참고한다.

<구조 요약>
segments –> Format, Version, NameCounter, SegCount, <SegName, SegSize>^SegCount
(segments파일이 포함하고 있는 인자들)

<각 인자별 자료형 정의>
Format, NameCounter, SegCount, SegSize –> UInt32 (Lucene 1.4에서는 Format이 -1)

Version –> UInt64

SegName –> String

<상세설명>
Version : 문서를 추가하고 삭제하면서 얼마나 색인이 변경되었는지 정도를 나타냄

NameCounter : 새로운 세그먼트의 이름을 생성하기 위한 카운터임 (1.4에서는 문서갯수와 관련된 이름을 생성했음.)

SegName : 세그먼트의 이름, 그러니까 파일명의 확장자명을 뺀 이름을 의미한다.
(버전에 따라 네이밍 생성 규칙이 다를수 있으나 같은 세그먼트라면 확장자 명을 뺀 나머지 부분은 같다.)

SegSize : 세그먼트에 포함된 Document의 갯수

여기서 세그먼트 병합 방법에 대해서 설명해보고자 한다.(당연 Sudo코드는 Python  코드이다. ㅎㅎ 필자가 확인해본 결과 자바코드도 크게 다르지 않았다.)

def maybeMergeSegments(self):
"""
증분 세그먼트 병합
"""
targetMergeDocs = self.mergeFactor
while targetMergeDocs <= self.maxMergeDocs:
# 목표값(mergeFactor^n)보다 작은 세그먼트들의 정보를 찾아낸다.
minSegment = len(self.segmentInfos)
mergeDocs = 0
minSegment -= 1
while minSegment >= 0:
si = self.segmentInfos[minSegment]
if si.docCount >= targetMergeDocs:
break
mergeDocs += si.docCount
minSegment -= 1
if mergeDocs >= targetMergeDocs: #찾았다.
self.mergeSegments(minSegment + 1)
else:
break
#타겟 싸이즈를 다시 제너레이트 시킨다.
targetMergeDocs *= self.mergeFactor

segmentInfos객체는 segments 파일 자체를 메모리에 올린 형태이다. 그래서 segmentInfos객체 안에는 segment정보객체가 포함되어 있다. (self는 클래스 객체 메서드나 변수로 보면 된다.)

중요한 Factor가 되는 것은 mergeFactor이다.
임시로 각 Document는 세그먼트화 되어서 메모리에 저장되어 있다. 그 메모리에 저장된 것들을  mergeFactor를 기준으로 한번씩 체크를 해가면서 merge할 Doc가 준비되면 하나의 세그먼트로 병합을 한다.

마지막 코드부분일 보자!

targetMergeDocs *= self.mergeFactor

가 보이는데 이부분은 만일 mergeFactor가 20이라면 첫번째 루프를 돌때 20개의 기준 문서만을 병합하는데 반해 두번째에는 문서의 갯수가 400개와 같거나 넘을때 하나의 세그먼트로 병합을 한다. 여기서 mergeFactor는 메모리에 저장되는 Document의 갯수를 의미함과 동시에 세그먼트의 갯수를 조절하는 역할까지 하는것이다. 19개까지의 문서는 RamDirectory에 모든 문서가 저장이 되고 20의 문서가 add됨과 동시에 독립된 하나의 세그먼트로 병합이 되고 20개의 문서가 들어있는 세그먼트가 20개가 생성됨과 동시에 하나의 세그먼트로 병합이 되는 것이다.
그래서 하나의 색인에는 20개 이상의 세그먼트는 존재하지 않게 된다.

2)락(Locks) 파일들
다른 프로세스가 인덱스를 사용하고 있음을 명시하는 파일. 임시저장디렉토리에 저장된다.
자바에서는 “java.io.tmpdir”가 가르키는 부분이 될 것이다.

파일 이름이 “commit.lock” 으로 되어 있을때,프로세스가 현재 “segments”을 쓰고 있더나,
이전의 세그먼트 인덱스 파일을 삭제하는 중일것이다.
또는 프로세스가 ‘segments’을 읽고 있는 것이거나 ‘segments’파일을 열고 있을것이다.
이 락 파일은 명명된 ‘segments’ 파일이 읽혀지고 나서 처리되기 전에 다른 프로세스에 의해 삭제되는걸 막기위해 사용된다.
소스코드 분석 결과 루씬에서는 segments를 병합할때 segments.new라는 임시 파일을 생성하고 그 파일에 새로운 병합된 세그먼트를 만든다음에 완전하게 만들어진 후에 segments.new를 segments로 rename한다. 아마 그때 사용되는 파일일 것이다.

파일 이름이 “write.lock”으로 되어 있을시, 한 프로세스가 현재 인덱스에 문서를 추가하는 중이거나 또는 인덱스에서 파일을 제거하는 중이다.
이 락파일은 같은 시간에 몇몇의 프로세스가 인덱스를 수정하려 시도하는것들을 막기위해 사용된다.

3)삭제정보(Deletable) 파일
파일 이름이 “deletable”인것은 더이상 인덱스에 의해서 사용되지 않는 파일의 이름을 가지고 있다.
그러나 그것들은 지워지지는 않으며 오직 파일이 열려있을 동안에 지워지지 않는 Win32하에서 사용된다.
다른 플랫폼에서는 이 파일은 오직 널 바이트만 가지고 있다.

<구조 요약>
Deletable –> DeletableCount, <DeletableName>^DeletableCount

<각 인자별 자료형 정의>
DeletableCount –> UInt32
DeletableName –> String

코드 측면에서 분석해 보면 win32하에 동작하는 부분에 대한 고려가 있는데 대부분의 파일 삭제 작업은 세그먼트 병합시에 이루어지는거 같다. 그래서 병합을 할때마다 전에 지우지 못한 파일 리스트를 정보파일에서 읽어와 삭제작업을 실시한다.

4)복합색인(Compound) 파일들
루씬 1.4부터 복합색일 파일은 기본이 되어 버렸다. 이것은 다음부터 설명할 파일들에 대한 컨테이너 역할만을 한다.

<구조요약>
Compound (.cfs) –> FileCount, <DataOffset, FileName>^FileCount, FileData^FileCount

<인자별 자료형 정의>
FileCount –> VInt
DataOffset –> Long
FileName –> String
FileData –> raw file data

색인파일 갯수는 세그먼트 개수와 더불어 Document에 사용한 필드 갯수에 따라 크게 달라진다. 그리고 문서 갯수가 늘어날때 마다 어느정도 mergeFactor에 따라 세그먼트가 한정적으로 늘어나기 때문에 순간 파일의 개방갯수가 엄청나게 많아질 가능성이 매우 크다. 운영체제마다 동시에 개방할 수 있는 파일 갯수에 제한을 걸었기 때문에 그에대한 대책으로 여러개의 세그먼트 파일을 하나로 모아둔 Compound파일을 사용한다. 그래서 루씬에서는 단 두개의 파일만 열어봄으로써 색인을 사용할 수 있다. 물론 옵션으로 빼놓아서 다중파일 방식으로 색인을 구성할 수도 있다. 또한 속도에서는 다중파일 색인이 약간 빠른것으로 테스트 결과가 나와있으며 이 부분에 대해서는 시스템 자원과 속도면에서의 비교가 개발자 측면에서 선행되어야 할듯 하다.

이 그림에서 붉은 화살표로 범위지어진 부분이 compound 파일 하나로 구성되는 영역이다.

p.s) 강좌 차례가 거의 Lucene index File Format 문서를 따라가고 있다. 물론 문서설명이 워낙에 잘 되어 있어서 문서 순서대로 따라가며 필요한 부분은 소스코드로 설명해 보았고 나름 소스를 보면서 깨달은 사항을 기재해 봤다.

CC BY-NC 4.0 [강좌]Lucene Index File Format-1 by from __future__ import dream is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.