Elastic Search

Ch05. 데이터 집계 - 집계

webmaster 2025. 9. 18. 22:17
728x90

집계는 데이터를 그룹화하고, 통계를 구하는 기능(SQL의 GroupBy와 유사하다)

엘라스틱서치와 데이터 분석

SQL

SELECT SUM(ratings) FROM movie_review GROUP BY movie_no;

Elastic Search

POST movie_search/_search
{
  "size": 0,
  "aggs": {
    "movie_no_agg": {
      "terms": {
        "field": "movie_no"
      },
      "aggs": {
        "ratings_agg": {
          "sum": {
            "field": "ratings"
          }
        }
      }
    }
  }
}
  • 엘라스틱서치는 많은 양의 데이터를 조각내어 관리한다.(문서의 수가 늘어나도 배치 처리보다 좀 더 실시간에 가깝게 문서를 처리할 수 있다)
  • SQL과 비교하여 더욱 강력한 집계 기능을 제공하며, 인덱스를 활용한 분산 처리가 가능하기 때문에 SQL보다 더 많은 데이터를 빠르게 집계할 수 있다.

엘라스틱서치가 집계에 사용하는 기술

캐시

  • 집계쿼리로 값 조회 시, 엘라스틱 서치의 마스터 노드가 여러 노드에 있는 데이터를 집계해 질의에 답변하게 되는데, 데이터 양이 클수록 집계에는 많은 양의 CPU와 메모리 자원이 소모된다.
    • 질의 속도도 늘어난다.
  • 엘라스틱서치의 캐시를 이용하면, 이를 해결할 수 있는데 캐시는 질의의 결과를 버퍼에 보관하며, 이후 같은 질의에 대한 결과를 버퍼에 보관된 결과를 반환한다.
    • 캐시 사용만으로 인덱스 성능을 대폭 상향시킬 수 있으며, 일반적으로 힙 메모리의 1%를 할당하고 있다.
    • "indices.requests.cache.size: 2%"로 캐시 메모리를 조절할 수 있다.
  • 엘라스틱 서치 캐시 종류
    • Node Query Cache
      • 노드의 모든 샤드가 공유하는 LRU 캐시로, 캐시 용량이 가득차면 사용량이 가장 적은 데이터를 삭제하고 새로운 결과를 캐싱한다.
      • 10% 필터 캐시가 메모리를 제공하며, 쿼리 캐싱을 사용하지 여부는 elasticsearch.yml 파일에 "index.queries.cache.enable:true"를 추가하면 된다(기본 true)
    • Shard Request Cache
      • 샤드(데이터를 분산 저장하기 위한 단위, 독립 인덱스)에서 수행된 쿼리의 결과를 캐싱한다.
      • 샤드의 내용이 변경되면 캐시가 삭제되기 때문에 빈번한 업데이트에서는 성능 저하를 일으킬 수 있다.
    • Field Data Cache
      • 엘라스틱 서치는 필드에서 집계 연산을 수행할 때는 모든 필드 값을 메모리에 로드하는데, 이 때문에 엘라스틱서치에서 계산되는 집계 쿼리는 성능측면에서 비용이 많이 든다.
      • Field Data Cache는 집계가 계산되는 동안 필드의 값을 메모리에 보관
참고
집계에서 사용하는 필드 중 문자열 형태의 필드를 사용한다면 Keyword 타입으로 지정해야 한다
Keyword 타입은 Text 타입과 달라 분석 과정을 수행하지 않기 때문에 집계 성능이 향상되기 때문이다.

Aggregation API 이해하기

{
	"query": { ... 생략 ... }
    "aggs" : { ... 생략 ... }   
}
  • 기존 검색 쿼리에 집계 구문을 추가하는 방식으로 검색 쿼리의 결과 집계를 할 수 있다.
  • 집계 종류
    • 버킷 집계: 쿼리 결과로 도출된 도큐먼트 집합에 대해 특정 기준으로 나눈 다음 나눠진 도큐먼트들에 대한 산술 연산을 수행
      • 나눠진 도큐먼트들의 모음들이 각 버킷에 해당한다.
    • 메트릭 집계: 쿼리 결과로 도출된 도큐먼트 집합에서 필드의 값을 더하거나 평균을 내는 등의 산술 연산을 수행
    • 파이프라인 집계: 다른 집계 또는 관련 메트릭 연산의 결과를 집계
    • 행렬 집계: 버킷 대상이 되는 도큐먼트의 여러 필드에서 추출한 값으로 행렬 연산을 수행
      • 이를 토대로 다양한 통계 정보를 제공하나, 아직은 공식적인 집계 연산으로 제공되지 않고 실험적인 기능으로 제공됨(사용 시 주의)
  • 엘라스틱서치는 집계를 중첩해서 사용할 수 있기 떄문(하위 집계가 상위 집계의 버킷을 다시 집계)에 유용하다.
    • 단, 중첩 횟수는 제한이 없으나 중첩할수록 성능이 하락하는 단점이 있다.

집계 구문의 구조

"aggregations": {
  "<aggregation_name>": {
    "<aggregation_type>": {
      <aggregation_body>
    },
    "meta": { <meta_data_body> },        // (선택)
    "aggregations": { <sub_aggregation> } // (선택, 중첩 집계 가능)
  }
}
  • 데이터를 집계하기 위해서는 "aggregations" 단어를 명시("aggs"로 줄이는 것도 가능)
  • "aggregation_name": 하위 집계의 이름을 입력한다. 이 이름은 집계의 결과 출력에 사용된다
  • "aggregation_type": 집계 유형을 적는다. terms, date_histogram, sum 과 같은 다양한 집계 유형을 지정할 수 있다.
  • "aggregation_body": "aggregation_type"에 맞춰 내용을 작성하면 된다.
  • "meta": 메타 데이터를 붙여서 결과와 함께 반환할 때 사용
  • "aggregation": 또 다른 집계를 중첩할 수 있다. 단, 같은 레벨에 집계를 정의할 때는 부수적인 성격의 집계만 정의

집계 영역

POST movie_search/_search
{
  "size": 0,
  "query": {
    "constant_score": {
      "filter": {
        "match": {
          "<필드명>": "<조건>"
        }
      }
    }
  },
  "aggs": {
    "<집계이름>": {
      "<집계타입>": {
        "field": "<필드명>"
      }
    },
    "all_movies": {
      "global": {},
      "aggs": {
         "<하위집계이름>": {
           "<집계타입>": {
             "field": "<필드명>"
          }
        }
      }
    }
  }
}
  • 질의와 함께 집계를 사용하면, 질의를 통해 반환된 문서들의 집합 내에서 집계를 수행한다.
  • 질의가 생략되면, 내부적으로 match_all 쿼리로 수행되어 전체 문서에 대한 집계가 수행된다.
  • 한 번의 집계를 통해 질의어에 해단되는 문서들 내에서도 집계를 수행하며, 전체 문서에 대해서도 집계를 수행해야 하는 경우에는 글로벌 버킷을 사용하면 질의 내에서 전체 대상으로 집계를 수행할 수 있다.

 

728x90