lucene_logo

Elasticsearch’s Index Structrue & Segment Merging

Index > Shard > Segment

elasticsearch_index_shard_segment

  • 인덱스(Index)는 다수의 샤드(Shard)로 구성
  • 샤드는 다수의 세그먼트(segment)로 구성

루씬 인덱스

Elasticsearch는 루씬(Lucene)을 기반으로하며, segment는 아래와 같은 구조로 이루어진다.

lucene_index

(출처: http://hackerlabs.org/blog/2011/10/01/hacking-lucene-the-index-format/)

  • 하나의 세그먼트에는 여러개의 문서(Document)가 색인되어 저장
    문서는 여러개의 필드(Field)를 가지며,
    analyzed된 필드는 여러개의 텀(Term)으로 구성된다

복합 파일(Compound File) 인덱스 vs. 다중 파일(Per-Segment File) 인덱스

인덱스를 구성하는 파일의 개수에 따라 복합 파일 인덱스와 다중 파일 인덱스로 구분된다.
복합 파일 인덱스는샤드당 1개의 인덱스 파일, 즉 1개의 세그먼트만 생성하는 경우이며,
다중 파일 인덱스는 샤드당 여러개의 인덱스 파일, 즉 여러개의 세그먼트로 구성되는 경우다.
Elasticsearch에서는 다중 파일 인덱스만을 지원한다.

다중 파일 인덱스의 장점은 증분 색인(incremental indexing)을 지원한다는 점이다.
즉 새로운 문서가 추가되더라도, 전체 문서를 재색인하지 않고, 추가된 문서들만 색인하면 검색이 가능해진다.

Elasticsearch의 증분색인 과정

예를 들어 인덱스가 3개의 세그먼트로 구성되어 있는 상태에서 새로운 문서가 추가되면,
문서는 인메모리 버퍼(in-memory buffer)이 저장되며 해당 색인 operation은 모두 트랜스로그(translog)에 모두 기록된다.

elasticsearch_incremental_indexing_phase1

(출처: https://www.elastic.co/guide/en/elasticsearch/guide/current/translog.html)

refresh 주기(refresh_interval, 기본 1초)가 지나면

  • 인메모리 버퍼에 저장된 문서는 새로운 세그먼트로 만들어지고 검색이 가능해지며,
  • 인메모리 버퍼는 비워진다

elasticsearch_incremental_indexing_phase2

(출처: https://www.elastic.co/guide/en/elasticsearch/guide/current/translog.html)

또다시 새로운 문서가 추가되면, 새로운 문서는 색인되어 인메모리 버퍼에 저장되고, 색인 operation은 트랜스로그에 누적되어 기록된다.

elasticsearch_incremental_indexing_phase3

(출처: https://www.elastic.co/guide/en/elasticsearch/guide/current/translog.html)

주기적으로 또는 기준 용량을 넘어서면 새로운 트랜스로그 파일이 생성되며, 인덱스는 full-cmmit이 실행된다.

  • 인메모리 버퍼에 추가 색인된 문서는 새로운 세그먼트로 만들어지며, 인메메로 버퍼는 비워진다
  • 새로운 커밋 포인트(commit point)가 기록된다
  • 파일 시스템 캐시는 fsync를 통해 물리 디스크로 플러쉬(flush)된다
  • 기존 트랜스로그는 삭제된다.

elasticsearch_incremental_indexing_phase4

(출처: https://www.elastic.co/guide/en/elasticsearch/guide/current/translog.html)

참고) 트랜스로그 생성 주기(full-commit 주기)
index.translog.flush_threshold_ops
기록할 최대 색인 operation 개수 (기본값: unlimited)
index.translog.flush_threshold_size
트랜스로그 파일 최대 가용 사이즈 (기본값: 512mb)
index.translog.flush_threshold_period
가장 최근에 플러쉬가 발생한 시간 (기본값: 30분)
index.translog.interva
플러쉬가 필요한지 검사할 주기. (기본값: 5초)

아래는 1개의 노드, 5개의 샤드, 0개의 레플리카(replica)로 구성된 인덱스의 파일 구조다.

elasticsearch_index_file_structure

세그먼트 병합(Segment Merging)

다중 파일 인덱스 특성으로 인해, refresh가 발생하면 새로운 세그먼트 1개가 생성되며 시간이 지나면서 세그먼트 수는 누적된다. Elasticsearch는 주기적으로 작은 세그먼트를 모아서 1개의 큰 세그먼트로 병합하는 작업을 백그라운드에서 실행한다. 이때 삭제된 문서까지도 색인에서 완전히 삭제하는 작업이 함께 수행된다.

예를 들어 인덱스가 완전히 커밋된 2개의 세그먼트와, 아직 커밋되지 않은 채 검색만 가능한 2개의 세그먼트로 구성된 경우,

elasticsearch_segment_merging_phase1

(출처: https://www.elastic.co/guide/en/elasticsearch/guide/current/merge-process.html)

주기적으로 사이즈가 비슷한 세그먼트를 합쳐서 1개의 큰 세그먼트로 병합한다.

elasticsearch_segment_merging_phase2
(출처: https://www.elastic.co/guide/en/elasticsearch/guide/current/merge-process.html)

병합 과정이 끝나면, 기존의 작은 세그먼트는 삭제된다.

세그먼트 병합은 많은 I/O와 CPU를 소모하게 된다. 따라서 병합 프로세스가 검색 성능에 영향을 주지 않도록 병합 프로세스는 throttling된다(indices.store.throttle.max_bytes_per_sec로 설정). 기본 값은 20MB/s이다.

Throttling은 노드 레벨과 인덱스 레벨에서 설정할 수 있다.

노드 레벨 throttling
indices.store.throttle.type
merge(기본값), all, none
indices.store.throttle.max_bytes_per_sec
20MB/s(기본값)

인덱스 레벨 throttling
index.store.throttle.type
node(기본값), merge, all, none
index.store.throttle.max_bytes_per_sec

optimize API를 사용하면 강제로 세그먼트를 즉시 병합하여 max_num_segments에 설정된 값만큼 세그먼트 수를 줄일 수 있다. 하지만 optimize API를 사용한 경우에는 throttling이 되지 않으므로, 가급적이면 사용하지 말아야 한다.

세그먼트 병합 성능 팁

SSD를 사용한다면 indices.store.throttle.max_bytes_per_sec을 100~200MB/S 상향 조정하기를 권한다.

SSD가 아니라면, 백그라운드에서 병합할 때 실행될 쓰레드 개수를 1로 설정한다.

병합 쓰레드 개수의 기본값은
Math.min(3, Runtime.getRuntime().availableProcessors() / 2)
이다

index.refresh_interval을 상향 조정한다. 인메모리버퍼가 리프레쉬될 때마다 새로운 세그먼트가 생성된다. 따라서 기본값(1초)을 사용할 경우, 1초마다 새로운 세그먼트가 생성된다. 신규 문서에 대한 실시간 검색 요건이 1초가 아니라면, 최대한 늘릴수록 생성되는 세그먼트 수는 줄어들게된다.

마찬가지로 트랜스로그가 플러쉬되는 주기가 짧을수록 생성되는 세거먼트 수도 줄어든다.
예를 들어 index.translog.flush_threshold_size를 기본값인 200mb에서 샹향조정한다.

반대로, 신규 인덱스를 위해 벌크 색인(bulk indexing)중이라면, 오히려 병합 과정의 throttling은 벌크 색인을 지연시킨다. 따라서 신규 색인이고 검색 성능은 전혀 고려하지 않아도 된다면, throttling을 하지 않도록 설정한다.

세그먼트 확인하기

인덱스의 세그먼트 수, 각 세그먼트의 상세 정보는 아래와 같이 확인할 수 있다.

elasticsearch_curl_segments

Merge 정책

TBD

https://www.elastic.co/guide/en/elasticsearch/reference/1.x/index-modules-merge.html

참고자료

Hacking Lucene – the Index Format
루씬 인 액션 부록 B, 루씬 색인 구조 / 에이콘 / 강철구 옮김
Elasticsearch: The Definitive Guide, Inside a Shard
Elasticsearch Reference[1.5], Translog
Elasticsearch: The Definitive Guide, Segment Merging
Elasticsearch Reference[1.5], Store
Elasticsearch: The Definitive Guide, Indexing Performance Tips

Leave a Reply

Your email address will not be published. Required fields are marked *