Skip to content

Star tree Index

집계(Aggregation)는 데이터 규모가 커질수록 집계 성능은 급격히 저하되며, 이로 인해 쿼리 지연(latency)과 리소스 소비가 증가하는 문제가 있습니다. 이를 해결하기 위해 OpenSearch 2.18부터 신규 기능인 Star-tree Index가 실험적으로 도입되었습니다.

Star-tree Index란?

Star-tree Index는 미리 집계된(Aggregated) 값을 다양한 차원 조합에 따라 저장하는 인덱스 구조입니다. 기존에는 쿼리 시점에 집계를 수행했지만, Star-tree는 인덱싱 시점에 각 조합별 집계를 미리 계산해 저장하므로, 검색 쿼리 시 빠르게 응답할 수 있습니다.

주요 특징

  • 멀티 필드 집계 최적화: 여러 필드의 조합에 대한 집계도 효율적으로 처리

  • 실시간 동작: 인덱싱 중 segment flush/refresh 시마다 star-tree 구조 생성

  • 쿼리 문법 변경 없음: 기존 쿼리 그대로 사용 가능하며, 자동 최적화 적용

  • 페이징 및 디스크 I/O 효율 향상: 적은 리프 탐색으로 빠른 응답 가능

Star-tree Index 구조

Star-tree는 트리 형태로 구성되며, 다음과 같은 구성요소를 포함합니다:

Dimension 노드 (ordered_dimensions)

  • 예: status, port, method

  • 트리의 경로를 구성하는 필드들

Metric 노드 (metrics)

  • 예: sum(size), avg(latency)

  • 리프 노드에 저장되는 사전 계산된 값들

Star 노드 (*)

  • 특정 차원에 대해 모든 값을 집계한 노드

  • 쿼리 조건이 없는 차원을 건너뛸 수 있도록 최적화

Leaf 노드

  • 지정된 조합에 대한 최종 metric 값 저장

  • max_leaf_docs 값으로 문서 수 제한 가능

설정 예시

PUT /logs
{
  "settings": {
    "index.composite_index": true,
    "index.append_only.enabled": true
  },
  "mappings": {
    "composite": {
      "request_aggs": {
        "type": "star_tree",
        "config": {
          "ordered_dimensions": [
            { "name": "status" },
            { "name": "port" },
            { "name": "method" }
          ],
          "metrics": [
            { "name": "size", "stats": ["sum"] },
            { "name": "latency", "stats": ["avg"] }
          ],
          "date_dimension": {
            "name": "@timestamp",
            "calendar_intervals": ["month", "day"]
          }
        }
      }
    },
    "properties": {
      "status": { "type": "integer" },
      "port": { "type": "integer" },
      "method": { "type": "keyword" },
      "size": { "type": "integer" },
      "latency": { "type": "scaled_float", "scaling_factor": 10 }
    }
  }
}

쿼리 예시 및 최적화 방식

쿼리는 기존 OpenSearch 쿼리와 동일하며, star-tree가 자동 적용됩니다.

1. 단일 조건 집

{
  "query": { "term": { "status": 500 } },
  "aggs": { "sum_size": { "sum": { "field": "size" } } }
}

status=500 노드에 미리 저장된 값에서 sum(size)를 즉시 반환

2. 날짜 기반 집계

{
  "size": 0,
  "query": { "range": { "status": { "gte": "200", "lte": "400" } } },
  "aggs": {
    "by_month": {
      "date_histogram": {
        "field": "@timestamp",
        "calendar_interval": "month"
      },
      "aggs": {
        "sum_size": {
          "sum": {
            "field": "size"
          }
        }
      }
    }
  }
}

→ 월 단위로 status 필터를 적용한 sum(size)를 빠르게 반환

3. Terms 집계

{
  "aggs": {
    "users": {
      "terms": {
        "field": "user_id"
      }
    }
  }
}

user_id가 dimension에 포함된 경우 star-tree로 최적화

4. Range 집계

{
  "aggs": {
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 100 },
          { "from": 100, "to": 500 },
          { "from": 500 }
        ]
      },
      "aggs": {
        "total_quantity": {
          "sum": {
            "field": "quantity"
          }
        }
      }
    }
  }
}

→ 범위 기반 버킷 집계도 star-tree로 처리 가능

주의사항 및 제한

항목 제한 내용
❌ 문서 수정/삭제 지원하지 않음 (append-only 인덱스 필요)
❌ _id와 같은 고유 필드 dimension으로 사용 금지 (고카디널리티로 인한 성능 저하)
❌ array 필드 지원하지 않음
❌ must_not, minimum_should_match Boolean 쿼리에서 지원되지 않음
✅ 지원 쿼리 term, terms, range, match_all, 일부 bool 쿼리
✅ 지원 집계 sum, avg, min, max, value_count, date_histogram, terms, range