Contents

Elasticsearch Aggregation 성능 향상

엘라스틱서치가 Full search 기능으로 잘 알려져 있긴하지만, 강력한 aggregation은 엘라스틱서치를 사용하는 또 다른 주요한 이유이기도 하다.

Aggregation은 키바나의 모든 곳에서 사용된다. 모든 키바나 visualization의 대시보드들은 Aggregation을 사용하는 Beats 에이전트로부터 모아진 데이터를 정리해서 보여준다.

여러 유즈 케이스에서 aggregation을 사용하는 경우 디자인적인 측면에서 좋지 않은 결정을 피하기 위한 몇 가지 주의 사항이 있다.

https://opster.com/guides/elasticsearch/how-tos/elasticsearch-aggregation-performance/

ES Aggregation의 성능 향상은 어떻게 이뤄질 수 있을까?

1. 도큐먼트 필터링을 통한 스코프 제한

query 절을 통해 최대한 많은 도큐먼트를 메모리에 올리지 않는 것이 가장 첫번째이다.

엘라스틱 서치는 분산 시스템이기 때문에 더 많은 데이터를 Aggregate의 대상으로 선정하는 순간 네트워크와 오케스트레이션 오버헤드가 따라서 증가하게 된다. 결과적으로 최종 성능과 처리 시간에도 영향을 미친다.

정확한 쿼리를 날리는 대신 비슷한 쿼리를 수행함으로써 성능 - 정확성 간의 트레이드 오프를 만들수도 있다. range 쿼리를 통해 범위를 제한하는 것이 그 예시이다.

2. 다른 샤드 설정 시도

샤딩은 엘라스틱서치의 분산 처리와 HA 기능을 가능하게 해주는 핵심 컴포넌트이다.

Aggregation의 관점에서, 필요한 개수의 샤드만 가지는 것은 성능에 있어서 드라마틱한 변화를 줄 수 있다.

샤드의 개수를 얼마나 할당할 것인지는 엘라스틱서치를 사용하는 입장에서 항상 고려되어야 할 사항이다. 유즈 케이스와 상황에 맞춰서 항상 달라지기 때문에 ‘매직 넘버’가 존재할 수 없기도 하다.

샤드 설정을 변경하려면 재색인(reindex) 과정이 필요하다. 그런데 샤드 개수를 변경하기 위해서 인덱스를 재색인하는 과정은 시스템에 큰 영향을 주기 때문에 운영 환경에서 수행하기에는 어려움이 있다.

샤드 설정을 변경하기 위해서

이럴 때 alias 뒤에 인덱스들을 숨기는 alias 패턴을 사용할 수 있다. alias 패턴은 다음과 같은 이점이 있다.

  • 현재 인덱스를 계속 사용하면서 오랜 기간 동안 실행되는 재색인 과정을 수행할 수 있다.
  • 다양한 버전의 인덱스를 사용할 수 있기 때문에, 새 인덱스 버전이 운영 환경에 반영되었을 때 문제가 발견되어도 쉽게 롤백할 수 있다.
  • A/B 테스트에 용이하다.

인덱스의 샤드 개수를 바꾸는 또 다른 방법은 shrink나 split API를 사용하는 것이다.

  • shrink API는 인덱스의 primary 샤드 개수를 줄이고, 나중에 증가시킬 때 사용할 수 있다.
  • 이 API들은 새 인덱스를 생성하는 과정을 추상화하고 인덱스의 설정을 변경하고 도큐먼트들을 옮긴다.
  • 이 API들은 소스 인덱스에서 대상 인덱스로 세그먼트들을 하드 링크하는 과정을 통해 이를 달성하려는 시도를 한다.

범할 수 있는 실수

이와는 별개로 샤드 수를 설정할 때 흔히 범하는 실수로는

  • 샤딩이 클러스터의 분산 병렬 처리의 이점을 가져다 주는 바운더리를 넘어
  • 오버헤드를 병목지점까지 올리는 오버샤딩을 수행하는 것이다.

3. 인덱싱 버퍼 갱신 주기 조절

도큐먼트가 생성, 업데이트, 삭제될 때에는 인덱싱 버퍼를 먼저 거친 후에 각 연산들이 수행된다.

엘라스틱서치는 이 임시 저장소의 내용들을 디스크의 다른 자료구조(세그먼트)로 flush하는 작업을

  • 세그먼트가 꽉 차거나
  • 미리 정해진 버퍼 갱신 주기에 도달했을 때 수행한다.

세그먼트들을 더 큰 세그먼트로 빈번하게 합치는 것의 문제는 오버헤드 비용이 발생한다는 점이다. 또 인덱스의 갱신 주기를 증가시킬 수 있다면 성능에 대한 이점 뿐만 아니라 클러스터가 쿼리를 수행하기 위한 리소스를 조금 더 할당할 수 있다는 것이라는 의미이기도 하다.

갱신을 가끔하게 된다는 것은 또한 global ordinals 연산을 덜 자주 수행하게 된다는 것이고, 이는 전체적인 aggregation 실행 성능을 증가시킨다.

4. size 파라미터를 0으로 설정

엘라스틱서치는 search hit들을 사용하지 않는다면 size 파라미터를 0으로 설정하는 것을 권고한다.

이 행동은 샤드 요청 캐시를 불필요하게 채우는 것을 막기 때문에, 전반적인 aggregation 성능을 증가시킬 수 있다.

5. 노드 / 샤드 캐시의 이점을 활용

기본적으로 클러스터에 대한 모든 요청은 접근 가능한 노드와 샤드들 중 하나에 할당된다.

_search API는 preference 파라미터를 받을 수 있다. 이 preference 파라미터는 클러스터가 어떻게 요청을 만족시키기 위해 적절한 노드나 샤드를 선택할지에 대한 옵션이다.

이 옵션을 사용한다면 노드/샤드의 캐싱의 이점을 활용할 수 있는데,

  • 클러스터는 요청을 제공된 preference를 바탕으로 동일한 샤드의 동일한 순서로 라우팅하기 때문이다.
  • 그리고 이 라우팅 순서는 클러스터 상태나 선택된 샤드가 변경되지 않는 한 유지된다.
POST /my-index-000001/_search?preference=my-custom-shard-string
{
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  },
  "aggs": {
    "my-agg-name": {
      "terms": {
        "field": "my-field"
      }
    }
  }
}

_ 언더스코어로 시작하지 않는 어떤 문자열이라도 preference 문자열로써 사용할 수 있다.

클러스터 상태나 선택된 샤드가 변경되지 않는다면 동일한 문자열을 사용하는 search API는 동일한 샤드에 동일한 순서로 전달될 것이다.

사용자의 세션을 나타내는 값을 preference 문자열로 사용하는 것은 권장되는 행위인데,

  • 사용자는 보통 여러 개의 쿼리들을 연속적으로 수행하고,
  • 결과의 범위를 좁히는 경우가 많기 때문이다.

이 설정은 search 요청을 다른 노드로 분산시켜서 노드 레벨에서의 캐싱의 이점을 활용하지 못하는 것을 방지한다.

_local 파라미터

preference 파라미터에 사용할 수 있는 특별한 값은 _local이 있다.

이 값을 사용한다면

  • 현재 요청을 처리하는 노드가 네트워크 오버헤드를 피하기 위해 로컬에서 이용가능한 샤드가 있는 경우에만 샤드를 사용하려고 시도한다.
  • 요청을 처리하기 위해 다른 노드에서만 사용할 수 있는 샤드의 데이터가 필요한 경우에는 adaptive replica를 폴백으로 사용한다.