본문 바로가기
WIKI 기술 지식 베이스

Index rollups

원문 보기 위키 갱신

출처: 문서

본문

인덱스 롤업

압축되지 않은 시계열 데이터는 결국 스토리지 비용을 증가시키고, 클러스터 상태에 부담을 주며, 집계 속도를 저하시킵니다. _인덱스 롤업_은 오래된 데이터를 주기적으로 압축하여 세분화된 요약 인덱스로 만들어 이러한 영향을 완화합니다.

관심 있는 필드를 선택하고 인덱스 롤업을 사용하여 해당 필드만 포함하고 더 큰 시간 버킷으로 집계된 새 인덱스를 만들 수 있습니다. 동일한 쿼리 성능으로 훨씬 적은 비용으로 수개월 또는 수년간의 기록 데이터를 저장할 수 있습니다.

예를 들어, 5초마다 CPU 사용량 데이터를 수집하여 핫 노드에 저장한다고 가정해 보겠습니다. 오래된 데이터를 읽기 전용 웜 노드로 이동하는 대신, 매주 간격을 10%씩 줄여 이 데이터를 점진적으로 압축할 수 있습니다. 또는 하루 평균 CPU 사용량만 저장할 수도 있습니다.

인덱스 롤업은 세 가지 방법으로 사용할 수 있습니다.

  1. 활발하게 수집되고 있지 않은 인덱스(예: 롤오버된 인덱스)에서 작동하는 온디맨드 인덱스 롤업 작업에는 Index Rollup API를 사용하세요. 예를 들어, 5분 간격으로 수집된 데이터를 주간 평균으로 집계하여 추세 분석을 수행하는 인덱스 롤업 작업을 실행할 수 있습니다.
  2. 정의된 일정에 따라 실행되는 인덱스 롤업 작업을 만들려면 OpenSearch Dashboards UI를 사용하세요. 또는 데이터가 수집되는 동안 인덱스를 롤업하도록 작업을 구성할 수도 있습니다. 예를 들어, Logstash 인덱스를 5초 간격에서 1시간 간격으로 지속적으로 롤업할 수 있습니다.
  3. 완전한 인덱스 관리의 일부로 인덱스 롤업 작업을 ISM 액션으로 지정하세요. 이렇게 하면 롤오버, 인덱스 수명이 특정 시점에 도달, 인덱스가 읽기 전용이 되는 등의 이벤트 후에 롤업을 트리거할 수 있습니다. 또한 롤오버와 인덱스 롤업 작업을 순차적으로 실행할 수 있습니다. 먼저 롤오버가 현재 인덱스를 웜 노드로 이동한 다음 인덱스 롤업 작업이 핫 노드에 최소화된 데이터로 새 인덱스를 생성합니다.

롤업 작업 구성

롤업 작업은 소스 인덱스에서 데이터를 읽고 요약된 문서를 대상 인덱스에 씁니다. 소스 인덱스는 변경되지 않으며, 작업이 생성된 후에는 인덱스 선택을 변경할 수 없습니다.

작업은 타임스탬프 필드를 기준으로 소스 문서를 집계합니다. 이때 모든 버킷의 길이가 동일한 고정 간격 또는 월과 같은 달력 단위를 따르며 길이가 같지 않을 수 있는 달력 간격을 사용할 수 있습니다. 추가 필드로 그룹화할 수 있습니다(모든 필드 유형에 대한 terms 집계와 숫자 필드에 대한 histogram 집계). 그리고 숫자 필드에 대해 avg, sum, max, min, value_count, cardinality 메트릭을 저장할 수 있습니다.

그룹화할 필드는 신중하게 선택하세요. 세분화된 필드는 소스 문서만큼 많은 롤업 문서를 생성하여 공간을 거의 절약하지 못합니다. 필드 순서가 중요합니다. 버킷이 가장 적은 필드부터 그룹화하세요. 예를 들어, 도시별 인구 통계 데이터 세트의 경우 도시별로 그룹화하고 인구 통계를 메트릭으로 저장하세요.

작업은 고정 간격 또는 cron 표현식으로 정의한 일정에 따라 실행되며, 실행 시간과 메모리를 절충하여 실행당 여러 페이지를 처리합니다. 수집이 완료될 시간을 확보하려면 실행 지연을 추가하세요. 10분 지연의 경우 오후 1시부터 2시까지의 시간을 롤업하는 실행이 오후 2시 10분에 시작됩니다. 작업을 연속으로 표시하면 한 번에 처리하는 대신 데이터가 수집되는 대로 롤업합니다.

작업을 생성하려면 Index rollups API를 사용하거나 롤업 작업 생성의 단계를 따르세요.

대상 인덱스 검색

_search API를 사용하여 대상 인덱스를 검색합니다. 쿼리는 대상 인덱스의 제약 조건과 일치해야 합니다. 그룹화하지 않은 필드에 대한 terms 집계나 저장하지 않은 메트릭에 대한 집계는 400 오류로 거부됩니다.

롤업 인덱스에서 date_histogram 아래에 중첩된 avg 하위 집계는 script_exception과 함께 400을 반환합니다. sum과 value_count를 사용하여 나누거나, 대신 avg를 terms 집계 아래에 중첩하세요. {: .note}

대상 인덱스에 있는 문서의 내부 구조에는 접근할 수 없습니다. OpenSearch는 대상 인덱스에 맞게 쿼리를 다시 작성하므로 소스 인덱스와 대상 인덱스에 동일한 쿼리를 사용할 수 있습니다.

대상 인덱스를 쿼리하려면 size를 0으로 설정하세요:

GET {target_index}/_search
{
  "size": 0,
  "query": {
    "match_all": {}
  },
  "aggs": {
    "avg_cpu": {
      "avg": {
        "field": "cpu_usage"
      }
    }
  }
}

오후 1시부터 오후 9시까지 시간 간격으로 롤업된 데이터를 수집하고 오후 7시부터 오후 11시까지 분 간격으로 실시간 데이터를 수집하는 시나리오를 생각해 보겠습니다. 동일한 쿼리에서 이들에 대해 집계를 실행하면 오후 7시부터 오후 9시까지 롤업된 데이터와 실시간 데이터가 모두 집계에서 두 번 계산되므로 중복이 발생합니다.

Cardinality 메트릭

Introduced 3.5 {: .label .label-purple }

Cardinality 메트릭은 HyperLogLog++(HLL++) 알고리즘을 사용하여 롤업된 데이터에서 고유 개수를 메모리 효율적으로 추적할 수 있게 해줍니다. 이는 사용자 ID, IP 주소 또는 세션 ID와 같이 모든 고유 값을 저장하는 데 비용이 많이 드는 높은 카디널리티 필드에 이상적입니다.

구성

롤업 작업에서 cardinality 메트릭을 정의할 때 다음 매개변수를 지정할 수 있습니다.

매개변수 데이터 유형 설명
precision_threshold 정수 정확도와 메모리 사용량 간의 균형을 제어합니다. 값이 높을수록 정확도는 높아지지만 더 많은 메모리를 사용합니다. 100에서 40,000 사이의 값을 사용하세요. 이 범위를 벗어나는 값은 오류 없이 허용되지만 지원되지 않습니다. 기본값은 3,000입니다.

다음과 같이 cardinality 객체에서 precision_threshold 매개변수를 지정할 수 있습니다:

{
  "metrics": [
    {
      "source_field": "user_id",
      "metrics": [
        {
          "cardinality": {
            "precision_threshold": 10000
          }
        }
      ]
    }
  ]
}

Cardinality 메트릭 쿼리

롤업 인덱스에서 cardinality 메트릭을 소스 인덱스에서와 동일한 방식으로 쿼리할 수 있습니다:

GET {rollup_index}/_search
{
  "size": 0,
  "aggs": {
    "unique_users": {
      "cardinality": {
        "field": "user_id"
      }
    }
  }
}

{% include copy-curl.html %}

롤업 인덱스를 쿼리할 때 쿼리에 지정된 precision_threshold는 무시됩니다. 시스템은 항상 롤업 작업 생성 시 구성된 정밀도 임계값을 사용합니다. 이는 저장된 HLL 스케치와의 일관성을 보장합니다. {: .important }

예제: 고유 방문자 추적

이 예제는 시간당 고유 방문자 수를 추적하는 롤업 작업을 생성합니다. 먼저 소스 인덱스를 생성하세요:

PUT web_logs
{
  "mappings": {
    "properties": {
      "timestamp": { "type": "date" },
      "visitor_id": { "type": "keyword" },
      "page_views": { "type": "integer" }
    }
  }
}

{% include copy-curl.html %}

그런 다음 롤업 작업을 생성하세요:

PUT _plugins/_rollup/jobs/visitor_rollup
{
  "rollup": {
    "description": "Unique visitors per hour",
    "enabled": true,
    "schedule": {
      "interval": {
        "period": 1,
        "unit": "Hours"
      }
    },
    "source_index": "web_logs",
    "target_index": "web_logs_hourly",
    "page_size": 1000,
    "dimensions": [
      {
        "date_histogram": {
          "source_field": "timestamp",
          "fixed_interval": "1h"
        }
      }
    ],
    "metrics": [
      {
        "source_field": "visitor_id",
        "metrics": [
          {
            "cardinality": {
              "precision_threshold": 10000
            }
          }
        ]
      },
      {
        "source_field": "page_views",
        "metrics": [
          {
            "sum": {}
          }
        ]
      }
    ]
  }
}

{% include copy-curl.html %}

롤업 작업은 구성된 간격이 경과한 후 첫 번째 실행 시 대상 인덱스를 생성합니다. 그 전까지 대상 인덱스를 검색하면 index_not_found_exception이 반환됩니다. 작업이 실행되었는지 확인하려면 GET _plugins/_rollup/jobs/visitor_rollup/_explain을 전송하세요. rollup_metadata가 null이면 아직 작업이 실행되지 않은 것입니다. {: .note}

롤업 인덱스 쿼리:

GET web_logs_hourly/_search
{
  "size": 0,
  "aggs": {
    "hourly_stats": {
      "date_histogram": {
        "field": "timestamp",
        "fixed_interval": "1h"
      },
      "aggs": {
        "unique_visitors": {
          "cardinality": {
            "field": "visitor_id"
          }
        },
        "total_page_views": {
          "sum": {
            "field": "page_views"
          }
        }
      }
    }
  }
}

{% include copy-curl.html %}

다중 계층 롤업

Introduced 3.5 {: .label .label-purple }

다중 계층 롤업을 사용하면 롤업의 롤업 작업을 생성하여 시간이 지남에 따라 데이터 세분성을 점진적으로 줄일 수 있습니다. 이는 최근 기간에는 세분화된 데이터를 유지하고 오래된 기간에는 점점 더 거친 데이터를 유지하려는 장기 데이터 보존 전략에 유용합니다.

다중 계층 롤업을 사용하면 롤업 작업의 계층 구조를 만들 수 있습니다:

Raw Data (5-second intervals)
    ↓ Tier 1 Rollup
Hourly Rollup (1-hour intervals)
    ↓ Tier 2 Rollup
Daily Rollup (1-day intervals)
    ↓ Tier 3 Rollup
Weekly Rollup (1-week intervals)

각 계층은 이전 계층의 롤업 인덱스를 소스로 사용하여 데이터를 쿼리할 수 있는 기능을 유지하면서 스토리지 요구 사항을 점진적으로 줄입니다.

전제 조건

다중 계층 롤업이 올바르게 작동하려면 다음 전제 조건을 충족해야 합니다:

  1. 모든 계층은 동일한 차원 필드를 사용해야 하며, 필드 이름과 유형이 일치해야 합니다.
  2. 각 계층의 간격은 이전 계층 간격의 배수여야 합니다(예: 5m → 1h → 1d).
  3. 모든 계층이 cardinality 메트릭을 사용하는 경우 동일한 precision_threshold 값을 사용해야 합니다.
  4. 두 번째 및 이후 계층의 소스 인덱스는 이전 계층에서 생성된 롤업 인덱스여야 합니다.
  5. 다음 계층을 생성하기 전에 소스 계층이 최소한 한 번의 롤업 실행을 완료해야 합니다. 빈 롤업 인덱스에서 롤업 작업을 생성하면 성공하지만 예기치 않은 결과가 발생합니다.

예제: 2계층 롤업 전략

이 예제는 사물 인터넷(IoT) 센서 데이터에 대한 2계층 롤업을 보여줍니다. Tier 1과 Tier 2로 구성됩니다:

  • 두 계층 모두 동일한 차원 필드(timestamp, sensor_id, location)를 사용합니다.
  • 두 계층 모두 동일한 메트릭 필드(temperature (avg/max/min), device_id (cardinality))를 사용합니다.
  • cardinality precision_threshold는 두 계층에서 동일합니다(10000).
  • Tier 2는 sensor_data_hourly(Tier 1의 출력)를 소스로 사용합니다.

소스 인덱스를 생성하고 몇 개의 문서를 추가하세요:

PUT sensor_data
{
  "mappings": {
    "properties": {
      "timestamp": { "type": "date" },
      "sensor_id": { "type": "keyword" },
      "location": { "type": "keyword" },
      "device_id": { "type": "keyword" },
      "temperature": { "type": "double" }
    }
  }
}

{% include copy-curl.html %}

POST _bulk?refresh=true
{ "index": { "_index": "sensor_data" } }
{ "timestamp": "2026-01-05T08:15:00", "sensor_id": "s1", "location": "warehouse", "device_id": "d1", "temperature": 21.4 }
{ "index": { "_index": "sensor_data" } }
{ "timestamp": "2026-01-05T08:45:00", "sensor_id": "s1", "location": "warehouse", "device_id": "d1", "temperature": 22.1 }
{ "index": { "_index": "sensor_data" } }
{ "timestamp": "2026-01-05T09:10:00", "sensor_id": "s2", "location": "cold-store", "device_id": "d2", "temperature": 4.8 }
{ "index": { "_index": "sensor_data" } }
{ "timestamp": "2026-01-05T10:05:00", "sensor_id": "s2", "location": "cold-store", "device_id": "d2", "temperature": 5.2 }

{% include copy-curl.html %}

Tier 1: 원시 데이터 → 시간별 롤업

PUT _plugins/_rollup/jobs/sensors_hourly
{
  "rollup": {
    "description": "Hourly rollup of raw sensor data",
    "enabled": true,
    "schedule": {
      "interval": {
        "period": 1,
        "unit": "Hours"
      }
    },
    "source_index": "sensor_data",
    "target_index": "sensor_data_hourly",
    "page_size": 1000,
    "dimensions": [
      {
        "date_histogram": {
          "source_field": "timestamp",
          "fixed_interval": "1h"
        }
      },
      {
        "terms": {
          "source_field": "sensor_id"
        }
      },
      {
        "terms": {
          "source_field": "location"
        }
      }
    ],
    "metrics": [
      {
        "source_field": "temperature",
        "metrics": [
          {"avg": {}},
          {"max": {}},
          {"min": {}}
        ]
      },
      {
        "source_field": "device_id",
        "metrics": [
          {
            "cardinality": {
              "precision_threshold": 10000
            }
          }
        ]
      }
    ]
  }
}

{% include copy-curl.html %}

Tier 2: 시간별 롤업 → 일별 롤업

PUT _plugins/_rollup/jobs/sensors_daily
{
  "rollup": {
    "description": "Daily rollup of hourly sensor data",
    "enabled": true,
    "schedule": {
      "interval": {
        "period": 1,
        "unit": "Days"
      }
    },
    "source_index": "sensor_data_hourly",
    "target_index": "sensor_data_daily",
    "page_size": 1000,
    "dimensions": [
      {
        "date_histogram": {
          "source_field": "timestamp",
          "fixed_interval": "1d"
        }
      },
      {
        "terms": {
          "source_field": "sensor_id"
        }
      },
      {
        "terms": {
          "source_field": "location"
        }
      }
    ],
    "metrics": [
      {
        "source_field": "temperature",
        "metrics": [
          {"avg": {}},
          {"max": {}},
          {"min": {}}
        ]
      },
      {
        "source_field": "device_id",
        "metrics": [
          {
            "cardinality": {
              "precision_threshold": 10000
            }
          }
        ]
      }
    ]
  }
}

{% include copy-curl.html %}

각 계층은 자체 간격으로 실행되므로 sensor_data_hourly는 첫 번째 시간별 실행 후에 나타나고 sensor_data_daily는 첫 번째 일별 실행 후에 나타납니다. {: .note}

다중 계층 롤업 쿼리

모든 계층을 독립적으로 쿼리하거나 여러 계층을 검색할 수 있습니다.

특정 계층 쿼리:

GET sensor_data_daily/_search
{
  "size": 0,
  "aggs": {
    "daily_avg_temp": {
      "date_histogram": {
        "field": "timestamp",
        "fixed_interval": "1d"
      },
      "aggs": {
        "max_temperature": {
          "max": {
            "field": "temperature"
          }
        },
        "unique_devices": {
          "cardinality": {
            "field": "device_id"
          }
        }
      }
    }
  }
}

{% include copy-curl.html %}

여러 계층 쿼리(인덱스 패턴 사용):

GET sensor_data_hourly,sensor_data_daily/_search
{
  "size": 0,
  "aggs": {
    "temperature_stats": {
      "date_histogram": {
        "field": "timestamp",
        "fixed_interval": "1d"
      },
      "aggs": {
        "max_temp": {
          "max": {
            "field": "temperature"
          }
        }
      }
    }
  }
}

{% include copy-curl.html %}

샘플 연습

이 연습에서는 OpenSearch Dashboards 샘플 전자상거래 데이터를 사용합니다. 추가하려면 OpenSearch Dashboards 홈 페이지로 이동하여 Try our sample data를 선택한 다음 Sample eCommerce orders에서 Add data를 선택하세요.

그런 다음 검색을 실행하세요:

GET opensearch_dashboards_sample_data_ecommerce/_search

예제 응답

{
  "took": 23,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4675,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "opensearch_dashboards_sample_data_ecommerce",
        "_id": "jlMlwXcBQVLeQPrkC_kQ",
        "_score": 1,
        "_source": {
          "category": [
            "Women's Clothing",
            "Women's Accessories"
          ],
          "currency": "EUR",
          "customer_first_name": "Selena",
          "customer_full_name": "Selena Mullins",
          "customer_gender": "FEMALE",
          "customer_id": 42,
          "customer_last_name": "Mullins",
          "customer_phone": "",
          "day_of_week": "Saturday",
          "day_of_week_i": 5,
          "email": "[email protected]",
          "manufacturer": [
            "Tigress Enterprises"
          ],
          "order_date": "2021-02-27T03:56:10+00:00",
          "order_id": 581553,
          "products": [
            {
              "base_price": 24.99,
              "discount_percentage": 0,
              "quantity": 1,
              "manufacturer": "Tigress Enterprises",
              "tax_amount": 0,
              "product_id": 19240,
              "category": "Women's Clothing",
              "sku": "ZO0064500645",
              "taxless_price": 24.99,
              "unit_discount_amount": 0,
              "min_price": 12.99,
              "_id": "sold_product_581553_19240",
              "discount_amount": 0,
              "created_on": "2016-12-24T03:56:10+00:00",
              "product_name": "Blouse - port royal",
              "price": 24.99,
              "taxful_price": 24.99,
              "base_unit_price": 24.99
            },
            {
              "base_price": 10.99,
              "discount_percentage": 0,
              "quantity": 1,
              "manufacturer": "Tigress Enterprises",
              "tax_amount": 0,
              "product_id": 17221,
              "category": "Women's Accessories",
              "sku": "ZO0085200852",
              "taxless_price": 10.99,
              "unit_discount_amount": 0,
              "min_price": 5.06,
              "_id": "sold_product_581553_17221",
              "discount_amount": 0,
              "created_on": "2016-12-24T03:56:10+00:00",
              "product_name": "Snood - rose",
              "price": 10.99,
              "taxful_price": 10.99,
              "base_unit_price": 10.99
            }
          ],
          "sku": [
            "ZO0064500645",
            "ZO0085200852"
          ],
          "taxful_total_price": 35.98,
          "taxless_total_price": 35.98,
          "total_quantity": 2,
          "total_unique_products": 2,
          "type": "order",
          "user": "selena",
          "geoip": {
            "country_iso_code": "MA",
            "location": {
              "lon": -8,
              "lat": 31.6
            },
            "region_name": "Marrakech-Tensift-Al Haouz",
            "continent_name": "Africa",
            "city_name": "Marrakesh"
          },
          "event": {
            "dataset": "sample_ecommerce"
          }
        }
      }
    ]
  }
}
...

인덱스 롤업 작업을 생성합니다. 이 예제는 order_date, customer_gender, geoip.city_name, geoip.region_name, day_of_week 필드를 선택하여 example_rollup 대상 인덱스로 롤업합니다:

PUT _plugins/_rollup/jobs/example
{
  "rollup": {
    "enabled": true,
    "schedule": {
      "interval": {
        "period": 1,
        "unit": "Minutes",
        "start_time": 1602100553
      }
    },
    "last_updated_time": 1602100553,
    "description": "An example policy that rolls up the sample ecommerce data",
    "source_index": "opensearch_dashboards_sample_data_ecommerce",
    "target_index": "example_rollup",
    "page_size": 1000,
    "delay": 0,
    "continuous": false,
    "dimensions": [
      {
        "date_histogram": {
          "source_field": "order_date",
          "fixed_interval": "60m",
          "timezone": "America/Los_Angeles"
        }
      },
      {
        "terms": {
          "source_field": "customer_gender"
        }
      },
      {
        "terms": {
          "source_field": "geoip.city_name"
        }
      },
      {
        "terms": {
          "source_field": "geoip.region_name"
        }
      },
      {
        "terms": {
          "source_field": "day_of_week"
        }
      }
    ],
    "metrics": [
      {
        "source_field": "taxless_total_price",
        "metrics": [
          {
            "avg": {}
          },
          {
            "sum": {}
          },
          {
            "max": {}
          },
          {
            "min": {}
          },
          {
            "value_count": {}
          }
        ]
      },
      {
        "source_field": "total_quantity",
        "metrics": [
          {
            "avg": {}
          },
          {
            "max": {}
          }
        ]
      }
    ]
  }
}

롤업 작업에 설정된 필드에 대한 terms 집계를 위해 example_rollup 인덱스를 쿼리할 수 있습니다. 원본 opensearch_dashboards_sample_data_ecommerce 소스 인덱스에서와 동일한 응답을 받게 됩니다:

POST example_rollup/_search
{
  "size": 0,
  "query": {
    "bool": {
      "must": {"term": { "geoip.region_name": "California" } }
    }
  },
  "aggregations": {
    "daily_numbers": {
      "terms": {
        "field": "day_of_week"
      },
      "aggs": {
        "per_city": {
          "terms": {
            "field": "geoip.city_name"
          },
          "aggregations": {
            "average quantity": {
               "avg": {
                  "field": "total_quantity"
                }
              }
            }
          },
          "total_revenue": {
            "sum": {
              "field": "taxless_total_price"
          }
        }
      }
    }
  }
}

예제 응답

{
  "took" : 14,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 281,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "daily_numbers" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Friday",
          "doc_count" : 59,
          "total_revenue" : {
            "value" : 4858.84375
          },
          "per_city" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Los Angeles",
                "doc_count" : 59,
                "average quantity" : {
                  "value" : 2.305084745762712
                }
              }
            ]
          }
        },
        {
          "key" : "Saturday",
          "doc_count" : 46,
          "total_revenue" : {
            "value" : 3547.203125
          },
          "per_city" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Los Angeles",
                "doc_count" : 46,
                "average quantity" : {
                  "value" : 2.260869565217391
                }
              }
            ]
          }
        },
        {
          "key" : "Tuesday",
          "doc_count" : 45,
          "total_revenue" : {
            "value" : 3983.28125
          },
          "per_city" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Los Angeles",
                "doc_count" : 45,
                "average quantity" : {
                  "value" : 2.2888888888888888
                }
              }
            ]
          }
        },
        {
          "key" : "Sunday",
          "doc_count" : 44,
          "total_revenue" : {
            "value" : 3308.1640625
          },
          "per_city" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Los Angeles",
                "doc_count" : 44,
                "average quantity" : {
                  "value" : 2.090909090909091
                }
              }
            ]
          }
        },
        {
          "key" : "Thursday",
          "doc_count" : 40,
          "total_revenue" : {
            "value" : 2876.125
          },
          "per_city" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Los Angeles",
                "doc_count" : 40,
                "average quantity" : {
                  "value" : 2.3
                }
              }
            ]
          }
        },
        {
          "key" : "Monday",
          "doc_count" : 38,
          "total_revenue" : {
            "value" : 2673.453125
          },
          "per_city" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Los Angeles",
                "doc_count" : 38,
                "average quantity" : {
                  "value" : 2.1578947368421053
                }
              }
            ]
          }
        },
        {
          "key" : "Wednesday",
          "doc_count" : 38,
          "total_revenue" : {
            "value" : 3202.453125
          },
          "per_city" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Los Angeles",
                "doc_count" : 38,
                "average quantity" : {
                  "value" : 2.236842105263158
                }
              }
            ]
          }
        }
      ]
    }
  }
}

doc_count 필드

버킷 집계의 doc_count 필드는 각 버킷에 수집된 문서 수를 포함합니다. 버킷의 doc_count를 계산할 때 문서 수는 각 요약 문서에 있는 사전 집계된 문서 수만큼 증가합니다. 롤업 검색에서 반환된 doc_count는 소스 인덱스의 일치하는 총 문서 수를 나타냅니다. 각 버킷의 문서 수는 소스 인덱스를 검색하든 롤업 대상 인덱스를 검색하든 동일합니다.

쿼리 문자열 쿼리

Query DSL에서 더 짧고 쉽게 작성할 수 있는 문자열을 활용하려면 쿼리 문자열을 사용하여 롤업 인덱스의 검색 쿼리를 단순화할 수 있습니다. 쿼리 문자열을 사용하려면 롤업 검색 요청에 다음 필드를 추가하세요:

"query": {
  "query_string": {
    "query": "field_name:field_value"
  }
}

{% include copy.html %}

롤업 작업이 차원으로 인덱싱한 필드만 쿼리할 수 있습니다. 다음 예제는 * 와일드카드 연산자가 있는 쿼리 문자열을 사용하여 sensor_data_hourly 롤업 인덱스에서 두 개의 location 차원 값을 검색합니다:

GET sensor_data_hourly/_search
{
  "size": 0,
  "query": {
    "query_string": {
      "query": "warehouse OR cold*",
      "default_field": "location"
    }
  },
  "aggs": {
    "by_location": {
      "terms": {
        "field": "location"
      },
      "aggs": {
        "by_sensor": {
          "terms": {
            "field": "sensor_id"
          },
          "aggs": {
            "average temperature": {
              "avg": {
                "field": "temperature"
              }
            }
          }
        }
      }
    }
  }
}

{% include copy-curl.html %}

응답에는 일치하는 위치당 하나의 버킷이 포함됩니다:

{
  "took": 52,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  },
  "aggregations": {
    "by_location": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "cold-store",
          "doc_count": 2,
          "by_sensor": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "s2",
                "doc_count": 2,
                "average temperature": {
                  "value": 5.0
                }
              }
            ]
          }
        },
        {
          "key": "warehouse",
          "doc_count": 2,
          "by_sensor": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "s1",
                "doc_count": 2,
                "average temperature": {
                  "value": 21.75
                }
              }
            ]
          }
        }
      ]
    }
  }
}

쿼리 문자열 쿼리 매개변수에 대한 자세한 내용은 Query string query를 참조하세요.

동적 대상 인덱스

ISM 롤업에서 target_index 필드는 각 롤업 인덱싱 시점에 컴파일되는 템플릿을 포함할 수 있습니다. 예를 들어, target_index 필드를 {% raw %}rollup_ndx-{{ctx.source_index}}{% endraw %}로 지정하면 소스 인덱스 log-000001이 대상 인덱스 rollup_ndx-log-000001로 롤업됩니다. 이를 통해 각 소스 인덱스에 대해 하나의 롤업 작업이 생성되어 데이터를 여러 시간 기반 인덱스로 롤업할 수 있습니다.

{% raw %}{{ctx.source_index}}{% endraw %}의 source_index 매개변수는 와일드카드를 포함할 수 없습니다. {: .note}

여러 롤업 인덱스 검색

데이터가 여러 대상 인덱스로 롤업된 경우 모든 롤업 인덱스에 대해 하나의 검색을 실행할 수 있습니다. 동일한 롤업이 있는 여러 대상 인덱스를 검색하려면 인덱스 이름을 쉼표로 구분된 목록 또는 와일드카드 패턴으로 지정하세요. 예를 들어, target_index가 {% raw %}rollup_ndx-{{ctx.source_index}}{% endraw %}이고 소스 인덱스가 log로 시작하는 경우 rollup_ndx-log* 패턴을 지정하세요. 또는 롤업된 log-000001 및 log-000002 인덱스를 검색하려면 rollup_ndx-log-000001,rollup_ndx-log-000002 목록을 지정하세요.

동일한 쿼리로 롤업 인덱스와 비롤업 인덱스를 혼합하여 검색하지 마세요. 요청은 200을 반환하지만 롤업 인덱스가 샤드 실패로 실패하므로 결과에는 비롤업 데이터만 포함됩니다. {: .warning}

예시

다음 예시는 doc_count 필드, 동적 인덱스 이름, 그리고 동일한 롤업으로 여러 롤업 인덱스를 검색하는 방법을 보여줍니다.

1단계: log로 별칭이 지정된 인덱스의 롤오버를 관리하기 위해 ISM용 인덱스 템플릿을 추가합니다.

PUT _index_template/ism_rollover
{
  "index_patterns": ["log*"],
  "template": {
   "settings": {
    "plugins.index_state_management.rollover_alias": "log"
   }
 }
}

2단계: 하나의 문서가 업로드된 후 이름이 log*로 시작하는 모든 인덱스를 롤오버하고, 개별 백킹 인덱스를 롤업하는 ISM 롤오버 정책을 설정합니다. 대상 인덱스 이름은 소스 인덱스 이름 앞에 문자열 rollup_ndx-를 추가하여 동적으로 생성됩니다.

PUT _plugins/_ism/policies/rollover_policy 
{ 
  "policy": { 
    "description": "Example rollover policy.", 
    "default_state": "rollover", 
    "states": [ 
      { 
        "name": "rollover", 
        "actions": [ 
          { 
            "rollover": { 
              "min_doc_count": 1 
            } 
          } 
        ], 
        "transitions": [ 
          { 
            "state_name": "rp" 
          } 
        ] 
      }, 
      { 
        "name": "rp", 
        "actions": [
          { 
            "rollup": { 
              "ism_rollup": { 
                "target_index": {% raw %}"rollup_ndx-{{ctx.source_index}}"{% endraw %}, 
                "description": "Example rollup job", 
                "page_size": 200, 
                "dimensions": [ 
                  { 
                    "date_histogram": { 
                      "source_field": "ts", 
                      "fixed_interval": "60m", 
                      "timezone": "America/Los_Angeles" 
                    } 
                  }, 
                  { 
                    "terms": { 
                      "source_field": "message.keyword" 
                    } 
                  } 
                ], 
                "metrics": [ 
                  { 
                    "source_field": "msg_size", 
                    "metrics": [ 
                      { 
                        "sum": {} 
                      } 
                    ]
                  } 
                ]
              } 
            } 
          } 
        ], 
        "transitions": [] 
      } 
    ], 
    "ism_template": { 
      "index_patterns": ["log*"], 
      "priority": 100 
    } 
  } 
}

3단계: log-000001이라는 인덱스를 생성하고 이에 대한 별칭 log를 설정합니다.

PUT log-000001
{
  "aliases": {
    "log": {
      "is_write_index": true
    }
  }
}

4단계: 이전에 생성한 인덱스에 4개의 문서를 인덱싱합니다. 두 개의 문서에는 "Success" 메시지가 있고, 두 개의 문서에는 "Error" 메시지가 있습니다.

POST log/_doc?refresh=true 
{ 
  "ts" : "2022-08-26T09:28:48-04:00", 
  "message": "Success", 
  "msg_size": 10 
}
POST log/_doc?refresh=true 
{ 
  "ts" : "2022-08-26T10:06:25-04:00", 
  "message": "Error", 
  "msg_size": 20 
}
POST log/_doc?refresh=true 
{ 
  "ts" : "2022-08-26T10:23:54-04:00", 
  "message": "Error", 
  "msg_size": 30 
}
POST log/_doc?refresh=true 
{ 
  "ts" : "2022-08-26T10:53:41-04:00", 
  "message": "Success", 
  "msg_size": 40 
}

첫 번째 문서를 인덱싱한 후 롤오버 작업이 실행되어 rollover_policy가 첨부된 인덱스 log-000002를 생성합니다. 그런 다음 롤업 작업이 실행되어 롤업 인덱스 rollup_ndx-log-000001을 생성합니다.

각 단계는 ISM 작업의 다음 실행을 기다리므로 전체 시퀀스는 여러 ISM 주기가 완료되는 데 약 20분(기본 job_interval 5분 기준)이 소요됩니다. 진행 상황을 확인하려면 GET _plugins/_ism/explain을 실행하고 상태 변화를 관찰하세요. {: .tip}

5단계: 롤업 인덱스를 검색합니다.

GET rollup_ndx-log-*/_search
{
  "size": 0,
  "query": {
    "match_all": {}
  },
  "aggregations": {
    "message_numbers": {
      "terms": {
        "field": "message.keyword"
      },
      "aggs": {
        "per_message": {
          "terms": {
            "field": "message.keyword"
          },
          "aggregations": {
            "sum_message": {
              "sum": {
                "field": "msg_size"
              }
            }
          }
        }
      }
    }
  }
}

응답에는 "Error"와 "Success"라는 두 개의 버킷이 포함되어 있으며, 각 버킷의 문서 수는 2입니다:

{
  "took" : 30,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "message_numbers" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Success",
          "doc_count" : 2,
          "per_message" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Success",
                "doc_count" : 2,
                "sum_message" : {
                  "value" : 50.0
                }
              }
            ]
          }
        },
        {
          "key" : "Error",
          "doc_count" : 2,
          "per_message" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "Error",
                "doc_count" : 2,
                "sum_message" : {
                  "value" : 50.0
                }
              }
            ]
          }
        }
      ]
    }
  }
}

인덱스 코덱 고려 사항

인덱스 코덱 고려 사항은 Index codecs를 참조하세요.

OpenSearch Dashboards의 인덱스 롤업

Index Management 페이지로 이동하려면 상단 메뉴에서 Management > Index Management로 이동하세요. Rollup jobs를 선택하여 클러스터의 롤업 작업 목록과 상태 및 다음 실행 시간을 확인하세요. 작업을 선택하여 구성 및 실행 결과를 볼 수 있습니다. 작업을 조치하려면 옆에 있는 확인란을 선택한 다음 Enable, Disable 또는 Actions > Delete를 선택하세요.

다음 이미지는 Rollup jobs 페이지를 보여줍니다.

롤업 작업 페이지

롤업 작업에는 타임스탬프 필드가 포함된 소스 인덱스가 필요합니다. 클러스터에 롤업할 시계열 데이터가 없는 경우 OpenSearch Dashboards 홈페이지에서 샘플 전자상거래 데이터를 추가하고 Sample walkthrough에 설명된 대로 order_date 필드를 롤업하세요.

롤업 작업 생성

  1. Index Management에서 Rollup jobs를 선택한 다음 Create rollup job을 선택하세요.
  2. 작업의 Name을 입력하고, 선택적으로 설명을 입력하세요.
  3. Source index에서 롤업할 인덱스 또는 인덱스 패턴을 선택하세요.
  4. Target index에서 기존 인덱스를 선택하거나 새 인덱스의 이름을 입력하세요. 이름에는 embedded variables를 포함할 수 있습니다.
  5. Next를 선택하세요.
  6. Time aggregation에서 다음을 수행하세요:
    1. 집계할 Timestamp field를 선택하세요.
    2. Interval type을 선택하세요. 고정 간격은 모두 동일한 길이입니다. 달력 간격은 월과 같은 달력 엔터티를 따르며 길이가 다를 수 있습니다.
    3. Interval에서 간격의 길이를 선택하세요.
    4. Timezone에서 타임스탬프의 시간대를 선택하세요.
  7. 선택적으로 Additional aggregation에서 그룹화할 필드를 추가하세요:
    1. Add fields를 선택하고 필드 이름을 선택한 다음 Add를 선택하세요.
    2. 각 필드에 대해 Aggregation method를 선택하세요. 키워드 필드는 용어로만 집계할 수 있습니다.
    3. 각 히스토그램 집계에 대해 Interval에 버킷당 타임스탬프 간격 수를 입력하세요.
    4. 선택적으로 버킷이 가장 적은 필드가 먼저 오도록 필드를 재정렬하세요.
  8. 선택적으로 Additional metrics에서 저장할 메트릭을 추가하세요:
    1. Add fields를 선택하고 숫자 필드 이름을 선택한 다음 Add를 선택하세요.
    2. 각 필드에 대해 저장할 메트릭을 선택하세요: Min, Max, Sum, Avg, Value count 또는 All. 테이블의 모든 필드에 대해 모든 메트릭을 저장하려면 Enable all을 선택하고, 모두 지우려면 Disable all을 선택하세요.
  9. Next를 선택하세요.
  10. Schedule에서 다음을 수행하세요:
    1. 정책이 호출할 때만이 아니라 자체 일정에 따라 작업을 실행하려면 Enable job by default를 선택한 상태로 유지하세요.
    2. 수집되는 대로 데이터를 롤업하려면 Continuous에서 Yes를 선택하세요.
    3. Rollup execution frequency에서 Define by fixed interval을 선택하고 Rollup interval을 입력하거나, Define by cron expression을 선택하고 cron 표현식과 시간대를 입력하세요. 표현식 구문은 Cron expressions를 참조하세요.
    4. Page per execution에서 각 실행에서 처리할 페이지 수를 입력하세요. 숫자가 클수록 더 빠르게 실행되고 더 많은 메모리를 사용합니다.
    5. 선택적으로 Execution delay에서 작업이 실행되기 전에 수집이 완료될 때까지 기다리는 시간을 입력하세요.
  11. Next를 선택하고 구성을 검토한 다음 Create를 선택하세요.

관련 문서

더 알아보기 (Learn more)