Elasticsearch 집계 -메트릭/버킷/조합/파이프라인 집계
[ELK Stack]Elasticsearch 집계 -메트릭/버킷/조합/파이프라인 집계
1. 집계의 요청 - 응답 형태
- Elasticsearch에서 집계는 검색 요청과 함께
_searchAPI를 통해 요청함 - 쿼리 요청 시
aggs또는aggregations키워드를 사용함 - 기본 구조:
GET index/_search
{
"size": 0,
"aggs": {
"집계_이름": {
"집계_타입": {
"field": "필드명"
}
}
}
}
size: 0을 통해 검색 결과는 제외하고 집계 결과만 확인 가능 (성능 최적화)
집계는 크게 두 가지로 나뉨:
| 유형 | 설명 | 예시 |
|---|---|---|
| 메트릭 집계 (Metric Aggregation) | 필드값 기반으로 통계값 계산 | 평균, 합계, 최대/최소값, 중간값, 유니크 개수 등 |
| 버킷 집계 (Bucket Aggregation) | 특정 조건에 따라 도큐먼트를 그룹핑 | 요일별, 범위별, 날짜별, 필터 조건 등 |
2. 메트릭 집계
자주 사용하는 메트릭 집계 종류
| 집계 타입 | 설명 |
|---|---|
avg |
필드의 평균값 |
min |
필드의 최솟값 |
max |
필드의 최댓값 |
sum |
필드의 합계 |
percentiles |
1/4, 중간값(50), 상위 백분위 등 |
stats |
평균/최소/최대/합계 등 통합 제공 |
cardinality |
유니크 값 개수 (DISTINCT) |
geo_centroid |
좌표 필드 평균 중심점 계산 |
2.1 평균값 / 중간값 구하기
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"stats_aggs": {
"avg": {
"field": "products.base_price"
}
}
}
}
- 평균 집계는 정수/실수형 필드에만 적용 가능
size: 0옵션으로 집계만 추출하여 리소스를 절감할 수 있음
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"stats_aggs": {
"percentiles": {
"field": "products.base_price",
"percents": [25, 50]
}
}
}
}
percentiles: 중간값(50%) 및 1사분위수(25%) 등의 위치 파악 가능- 실무에서는 가격 중앙값 등 데이터 분포 확인에 유용함
2.2 필드의 유니크한 값 개수 확인 (카디널리티)
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"cardi_aggs": {
"cardinality": {
"field" : "day_of_week",
"precision_threshold": 100
}
}
}
}
cardinality는 SQL의COUNT(DISTINCT)처럼 동작함precision_threshold: 정확도 조절 값으로 높을수록 정확하지만 리소스 사용량 증가
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"cardi_aggs": {
"cardinality": {
"field" : "day_of_week",
"precision_threshold": 5
}
}
}
}
- 위 쿼리에서는 실제 7개의 요일이 존재하지만, 낮은 threshold로 인해 결과값이 8로 나올 수 있음;;
- 그래서 이 파라미터는 실제결과보다 크게 잡아야한다는게 정설
2.3 검색 결과 내에서의 집계
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"query": {
"term": {
"day_of_week": {
"value": "Monday"
}
}
},
"aggs": {
"query_aggs": {
"sum": {
"field": "products.base_price"
}
}
}
}
- 집계하기전에 쿼리를 통해 도큐먼트 범위를 제한하고 용어수준 쿼리인 용어쿼리를 이용해 월요일도큐먼트값만 골라내서 이걸로 집계함
- 쿼리를 먼저 실행한 뒤 해당 결과에만 집계를 적용하는 방식
- 필터링된 문서만 대상으로 합계나 평균 계산이 가능함
3. 버킷 집계
자주 사용하는 버킷 집계 종류
| 집계 타입 | 설명 |
|---|---|
histogram |
숫자형 필드 기준 간격 나누기 |
date_histogram |
날짜 필드 기준 간격 나누기 |
range |
사용자 정의 범위 버킷 구간 설정 |
date_range |
날짜 범위 기반 그룹핑 |
terms |
필드값으로 그룹핑 (예: 요일별) |
significant_terms |
통계적으로 특이한 용어 그룹화 |
filters |
복수 필터 조건 기반 그룹화 |
3.1 히스토그램 집계
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"histogram_aggs": {
"histogram": {
"field": "products.base_price",
"interval": 100
}
}
}
}
- 숫자형 필드를 일정 간격 단위로 나눠 그룹핑
interval: 각 버킷의 간격- 히스토그램과 비슷하게 날짜 히스토그램집계도 있음 (날짜/시간필드사용하면서 간격이 숫자가 아닌 날짜/필드)
3.2 범위 집계
- 히스토그램은 각 버킷의 단위를 동일하게 지정할 수밖에 없는게 단점인데, 범위집계는 특정구간에 데이터가 몰려있거나, 데이터 편차가 큰 경우도 비효율적
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"histogram_aggs": {
"range": {
"field": "products.base_price",
"ranges": [
{"from":0,"to":50},
{"from":50,"to":100},
{"from":100,"to":200},
{"from":200,"to":1000}
]
}
}
}
}
- 범위에 맞게 버킷을 유연하게 나누는 방식
- 데이터가 비선형적으로 분포되어 있을 경우 적합함
3.3 용어 집계 (Terms Aggregation)
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"term_aggs": {
"terms": {
"field": "day_of_week",
"size": 6
}
}
}
}
- 범주형 필드(문자열) 기준으로 집계
size설정을 잘못하면 일부 값이 누락되며,sum_other_doc_count로 묶임
용어집계가 정확하지 않은 이유
-
용어집계가 부정확도를 표시하는 이유는 분산시스템의 집계 과정에서 발생하는 잠재적인 오류 가능성 때문임
-
분산시스템은 데이터를 여러 노드에서 분산하고 취합하는 과정에서 오류 발생 가능성
-
엘라스틱서치는 샤드에 도큐먼트를 저장하고 이를 분산하는데 size설정값과 샤드 개수등에 의해 집계오류 발생할수 있음
-
예를들어 실제결과와 용어집계가 다르다 -> 집게가 모든 도큐먼트를 가져와 한번에 집계하는게 아니라 분산되어있는 개별 노드단에서 먼저 집계를 하고 그 결과를 취합해 다시 집계를 하기 때문! 그래서 이러한 응답결과가 “doc_count_error_upper_bound”에 표시됨
용어 집계 정확성 높이기
고속처리를 위한 리소스와 속도간 트레이드오프의 일환으로 리소스 소비량을 늘리면 정확도를 높일 수 있음
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"term_aggs": {
"terms": {
"field": "day_of_week",
"size": 6,
"show_term_doc_count_error": true
}
}
}
}
- “show_term_doc_count_error”파라미터를 추가하면 버킷마다 “doc_count_error_upper_bound”값을 확인가능!!!
- 만약 확인결과 이상값이; 나올 경우에는 샤드 크기 파라미터를 늘릴 필요가 있음 “shard_size”
- 샤드 크기는 용어집계과정에서 개별 샤드에서 집계를 위해 처리하는 개수, 높게 설정하면 정확도가 올라가지만 리소스사용량도 업업-> 성능 떨어질수 있음
- 정확한 카운트를 보장하기 위해
show_term_doc_count_error,shard_size등을 활용해야 함 - 오차범위가 발생하는 이유: 각 샤드에서 병렬로 집계된 값을 중앙에서 병합하는 방식 때문
4. 집계의 조합
4.1 버킷 집계 + 메트릭 집계
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"term_aggs": {
"terms": {
"field": "day_of_week",
"size": 5
},
"aggs": {
"avg_aggs": {
"avg": {
"field": "products.base_price"
}
},
"sum_aggs": {
"sum": {
"field": "products.base_price"
}
}
}
}
}
}
- 요일별 버킷으로 나눈 후 각 버킷마다 평균, 합계를 계산함
- 버킷마다 여러 개의 메트릭 집계를 중첩 가능
4.2 서브 버킷 집계 (Nested Bucket)
- 서브버킷은 버킷 안에서 다시 버킷 집계를 요청하는 집계임 트리구조를 떠올리면 됨
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"histogram_aggs": {
"histogram": {
"field": "products.base_price",
"interval": 100
},
"aggs" : {
"term_aggs": {
"terms": {
"field": "day_of_week",
"size" : 2
}
}
}
}
}
}
- 가격을 기준으로 히스토그램 집계를 한 뒤, 각 가격대에서 요일별로 재집계
- 서브버킷을 과도하게 중첩하면 클러스터 부하로 이어질 수 있음 (2단계 이상은 주의)
5. 파이프라인 집계 (Pipeline Aggregation)
-
이전결과를 다음단계에서 이용하는 파이프라인 개념을 사용한 집계방식, 이전 집계결과를 입력으로 삼아 다시 집게하는 방식
-
그래서 부모집계, 형제집계라는 두가지 유형이 있음, 이 두가지 차이는 집계가 작성되는 위치임.
Elasticsearch 파이프라인 집계 종류 정리
구분 집계 명 설명 형제집계 (Sibling Pipeline Aggregation) min_bucket하위 버킷들 중 가장 작은 값을 가진 버킷의 값을 반환 max_bucket하위 버킷들 중 가장 큰 값을 가진 버킷의 값을 반환 avg_bucket하위 버킷들의 값의 평균값을 계산 sum_bucket하위 버킷들의 값의 총합을 계산 stats_bucket하위 버킷들의 값으로부터 count, min, max, avg, sum 등의 통계치를 제공 percentiles_bucket하위 버킷들 값의 퍼센타일 값을 계산 (예: 50%, 90% 등) moving_fnmoving_avgmoving_sum이동 평균, 합계, 사용자 정의 함수를 적용한 버킷 기반 시계열 스무딩 처리 bucket_script버킷 값들에 대해 사용자 정의 수식을 적용할 수 있음 부모집계 (Parent Pipeline Aggregation) derivative시계열 값의 변화량(차분)을 계산 (ex: 오늘 - 어제) cumulative_sum이전 값들을 누적하여 누적합을 계산 serial_diff시계열에서 n개 전 값과의 차이 계산 - 형제 집계는 동일한 레벨의 버킷 결과들을 기반으로 함 (ex:
date_histogram결과 각각에 대해 처리). - 부모 집계는 자식 집계 결과를 바탕으로 상위 집계 단계에서 후처리하는 방식임.
moving_avg는 Elasticsearch 8.0부터 deprecated 되었고,moving_fn으로 대체됨.bucket_script는 복수의 버킷 값을 조합한 계산 가능 (ex: A / B)
5.1 부모 집계 (Parent Pipeline)
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"histogram_aggs": {
"histogram": {
"field": "products.base_price",
"interval": 100
},
"aggs": {
"sum_aggs": {
"sum": {
"field": "taxful_total_price"
}
},
"cum_sum": {
"cumulative_sum": {
"buckets_path": "sum_aggs"
}
}
}
}
}
}
- 누적합(cumulative_sum)은 이전 메트릭 결과를 기반으로 집계하는 방식
- 반드시
buckets_path로 입력값 메트릭을 참조해야 함
5.2 형제 집계 (Sibling Pipeline)
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"term_aggs": {
"terms": {
"field": "day_of_week",
"size": 2
},
"aggs": {
"sum_aggs": {
"sum": {
"field": "products.base_price"
}
}
}
},
"sum_total_price": {
"sum_bucket": {
"buckets_path": "term_aggs>sum_aggs"
}
}
}
}
- 형제 파이프라인 집계는 최상단에서 참조된 집계 경로를 따라 새로운 계산 수행
- 이 경우 각 요일별
sum_aggs의 값을 모두 더해 하나의 결과로 반환 buckets_path: 중첩 경로는버킷명>집계명으로 표현
끄읕
댓글남기기