카디널리티 집계

카디널리티 집계 (Cardinality aggregation)

cardinality 집계는 필드에서 고유한(distinct) 값의 개수를 세어주는 단일 값(single-value) 메트릭 집계예요. 결과값은 근사치라는 점을 기억하세요. 자세한 내용은 정밀도 제어(Controlling precision) 섹션을 참고하세요.

출처: 문서

본문

파라미터

cardinality 집계는 다음과 같은 파라미터를 받아요.

파라미터 필수/선택 데이터 타입 설명
field 필수 String 카디널리티를 추정할 필드예요.
precision_threshold 선택 Numeric 이 값 이하에서는 개수가 정확할 것으로 기대되는 임계값이에요. 정밀도 제어(Controlling precision) 섹션을 참고하세요.
execution_hint 선택 String 집계 실행 방식을 지정해요. 유효한 값은 ordinals와 direct예요.
missing 선택 필드와 동일한 타입 필드 값이 없는 문서를 저장할 버킷이에요. 지정하지 않으면 누락 값은 무시돼요.

예제

다음 예제 요청은 OpenSearch Dashboards e-커머스 샘플 데이터에서 고유한 상품 ID의 개수를 찾아요:

GET opensearch_dashboards_sample_data_ecommerce/_search
{
  "size": 0,
  "aggs": {
    "unique_products": {
      "cardinality": {
        "field": "products.product_id"
      }
    }
  }
}

예제 응답

다음 예제 응답에서 볼 수 있듯이, 집계는 unique_products 변수에 카디널리티 개수를 반환해요:

{
  "took": 176,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4675,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  },
  "aggregations": {
    "unique_products": {
      "value": 7033
    }
  }
}

정밀도 제어 (Controlling precision)

정확한 카디널리티 계산은 모든 값을 해시 세트(hash set)에 로드한 뒤 그 크기를 반환하는 방식이에요. 이 방식은 확장성이 좋지 않아요. 엄청난 양의 메모리가 필요하고 지연 시간이 높아질 수 있어요.

precision_threshold 설정을 사용하면 메모리와 정확도 사이의 트레이드오프를 제어할 수 있어요. 이 파라미터는 개수가 정확할 것으로 기대되는 임계값을 설정해요. 이 값을 넘는 개수는 정확도가 떨어질 수 있어요.

precision_threshold의 기본값은 3,000이고, 지원되는 최댓값은 40,000이에요.

cardinality 집계는 HyperLogLog++ 알고리즘을 사용해요. 카디널리티 개수는 일반적으로 정밀도 임계값까지 매우 정확하며, 임계값이 100처럼 낮더라도 대부분의 경우 실제 개수와 6% 이내의 오차를 보여요.

해시 미리 계산하기 (Precomputing hashes)

카디널리티가 높은 문자열 필드의 경우, 인덱스 필드에 해시 값을 저장하고 해시의 카디널리티를 계산하는 방식이 연산량과 메모리 리소스를 절약할 수 있어요. 이 방식은 긴 문자열과/또는 높은 카디널리티를 가진 세트에서만 효율적이므로 신중하게 사용하세요. 숫자 필드와 메모리를 덜 차지하는 문자열 세트는 직접 처리하는 것이 더 좋아요.

예제: 정밀도 제어하기

정밀도 임계값을 고유 값 10000개로 설정해 봐요:

GET opensearch_dashboards_sample_data_ecommerce/_search
{
  "size": 0,
  "aggs": {
    "unique_products": {
      "cardinality": {
        "field": "products.product_id",
        "precision_threshold": 10000
      }
    }
  }
}

응답은 기본 임계값을 사용한 결과와 유사하지만, 반환된 값이 약간 달라요. precision_threshold 파라미터를 바꿔가며 카디널리티 추정값이 어떻게 달라지는지 확인해 보세요.

집계 실행 구성 (Configuring aggregation execution)

execution_hint 설정을 사용해 집계가 실행되는 방식을 제어할 수 있어요. 이 설정은 두 가지 옵션을 지원해요:

  • direct – 필드 값을 직접 사용해요.
  • ordinals – 필드의 순서 값(ordinal)을 사용해요.

execution_hint를 지정하지 않으면 OpenSearch가 하이브리드 컬렉터(기본 활성화)를 사용해 필드에 가장 적합한 옵션을 자동으로 선택해요.

순서 필드(ordinal field)가 아닌 곳에 ordinals를 설정해도 효과가 없어요. 마찬가지로 순서 필드에는 direct가 효과가 없어요.

이것은 고급 수준(expert-level) 설정이에요. ordinals는 필드의 카디널리티에 따라 크기가 결정되는 바이트 배열을 사용해요. 카디널리티가 높은 필드는 상당한 힙 메모리를 소비해 메모리 부족(OutOfMemory) 오류 위험을 높일 수 있어요.

예제: 실행 제어하기

다음 요청은 ordinals를 사용해 카디널리티 집계를 실행해요:

GET opensearch_dashboards_sample_data_ecommerce/_search
{
  "size": 0,
  "aggs": {
    "unique_products": {
      "cardinality": {
        "field": "products.product_id",
        "execution_hint": "ordinals"
      }
    }
  }
}

하이브리드 컬렉터 (Hybrid collector)

3.4 버전에서 도입됨

기본적으로 OpenSearch는 카디널리티 집계에 하이브리드 컬렉터를 사용해 속도를 높이고 메모리를 관리해요. 하이브리드 컬렉터는 더 빠른 ordinals 컬렉터로 시작해 실행 중 메모리 사용량을 모니터링해요. 사용량이 설정된 임계값을 초과하면 이미 계산된 데이터에서 이어서 direct 컬렉터로 자동 전환해요.

이 방식은 메모리가 충분할 때 더 빠른 성능을 제공하면서도 카디널리티가 높은 필드에 대한 안전성을 유지해요. 실제 메모리 상황에 동적으로 적응하며, 컬렉터를 전환할 때 집계를 다시 시작하는 오버헤드를 피할 수 있어요.

하이브리드 컬렉터를 구성하려면 다음 클러스터 설정을 사용하세요.

  • search.aggregations.cardinality.hybrid_collector.enabled (Dynamic, Boolean): 하이브리드 컬렉터를 활성화해요. 비활성화하면 OpenSearch는 기존 로직을 사용해 ordinals와 direct 컬렉터 중에서 선택해요. 기본값은 true예요.
  • search.aggregations.cardinality.hybrid_collector.memory_threshold (Dynamic, 백분율 또는 바이트 크기): ordinals에서 direct 컬렉터로 전환할 메모리 임계값을 설정해요. 이 설정을 JVM 힙의 백분율(예: 1%) 또는 절대값(예: 10mb 또는 1gb)으로 지정할 수 있어요. 기본값은 1%예요.

누락 값 처리 (Missing values)

집계 대상 필드의 값이 없는 문서에 특정 값을 할당해 줄 수 있어요. 자세한 내용은 누락 값 집계(Missing aggregations) 문서를 참고하세요.

카디널리티 집계에서 누락 값을 대체하면 대체 값이 고유 값 목록에 추가되어 실제 카디널리티가 1만큼 증가해요.

더 알아보기 (Learn more)