본문 바로가기
Computer/Elasticsearch

eager, eager global ordinals

by hexists 2015. 5. 6.

http://www.elastic.co/guide/en/elasticsearch/guide/current/preload-fielddata.html


ES는 기본적으로 fielddata를 lazily load 한다.

ES는 particular field에 fielddata가 필요한 query가 생기면, 전체 field를 각 index의 segement에 대해 메모리로 load한다.


작은 segments에서는 이 시간이 별로 안 걸리지만, 5GB segments는 10GB fielddata를 메모리로 올려야 한다. 이 과정은 수십초가 걸린다.


지연에 대비할 수 있는 3가지 방법이 있다.

1) Eagerly load fielddata

2) Eagerly load global ordinals

3) Prepopulate caches with warmers



1) Eagerly load fielddata

eager loading이 설정된 field는 검색이 가능하기전 각 segement에 미리 로딩된다.


PUT /music/_mapping/_song

{

  "price_usd": {

    "type": "integer",

    "fielddata": {

      "loading" : "eager" 

    }

  }

}


2) Eagerly load global ordinals


fielddata에 사용될 메모리 사용량을 줄일 수 있는 방법은 ordinals를 사용하는 것이다.


만약, 10억개의 문서들에 status field가 있다고 해보자. 

3가지 상태(status_pending, status_published, status_deleted)가 있다고 할 때,

우리는 각 문서에 전체 문자열을 저장한다면 14 ~ 16 bytes가 필요하고, 전체크기는 15GB가 필요하다.


그 대신, 우리는 세가지 unique strings을 사용할 수 있다. 0, 1, 2


Ordinal | Term

-------------------

0       | status_deleted

1       | status_pending

2       | status_published


원래 문자열은 ordinals list에 한번만 저장되고, 각 문서는 오직 ordinal을 가리키는 숫자를 사용한다.


Doc     | Ordinal

-------------------------

0       | 1  # pending

1       | 1  # pending

2       | 2  # published

3       | 0  # deleted


그러나 여기에 문제가 있다. fielddata caches는 segment 단위로 저장된다.

만약 segment가 오직 2가지 상태를 포함한다면 status_deleted, status_published

그러면 ordinals는 3가지 상태를 가진 segment의 ordinal과 다르다.


만약 우리가 status field에 대해 term aggregation을 하려고 한다면, 우리는 실제 문자열 값이 필요하다.

이것은 모든 segments에 대해 같은 값을 구별할 필요가 있다는 것을 의미한다.


global ordinals 구조를 사용하면 모든 segments에 대해 ordinals를 저장한다.


Building global ordinals


global ordinals는 fielddata와 doc values 메모리 위에 빌드되어 있다.

실제로, doc values가 그것처럼 주요한 이유다.


fielddata loading과 같은 방식으로 global ordinals 가 lazily하게 빌드된다.

refresh, flush, merge 후에 rebuilt된다.


PUT /music/_mapping/_song

{

  "song_title": {

    "type": "string",

    "fielddata": {

      "loading" : "eager_global_ordinals" 

    }

  }

}


Ordinals는 오직 strings에 대해서만 빌드된다.

숫자 데이터는 그 자체로 oridinal mapping 된다.


doc values를 사용한 예제


PUT /music/_mapping/_song

{

  "song_title": {

    "type":       "string",

    "doc_values": true,

    "fielddata": {

      "loading" : "eager_global_ordinals" 

    }

  }

}


이렇게 하면, fielddata는 filesystem cache에 로드된다.


fielddata preloading과는 다르게, global ordinals의 eager building은 데이터의 real-time에 영향을 받는다.

매우 높은 cardinality fields에 대해서는 refresh에 수초가 딜레이 될 수 있다. 그래서, refresh 또는 query시에 building할지 선택해야 한다.

만약 인덱스가 query가 빈번하지 않다면, refresh보다 query시에 build 하는 것이 더 낫다.


* elastic.co에 있는 문서를 번역한 내용입니다.

필요에 따라 생략한 부분도 있습니다.

'Computer > Elasticsearch' 카테고리의 다른 글

elasticsearch thread pool  (0) 2015.05.07
doc values  (0) 2015.05.06
Field data  (0) 2015.05.06
shard 상태 확인  (0) 2015.03.09
Elasticsearch Korea User Group  (0) 2015.02.09