Spec-Zone.ru › Elasticsearch 8
›Elasticsearch Guide [8.17] ›Агрегации ›Метрические агрегации

Агрегация процентильных рангов

Метрическая агрегация multi-value, которая рассчитывает один или несколько процентильных рангов по числовым значениям, извлечённым из агрегированных документов. Эти значения могут быть извлечены из определённых числовых или полевых данных гистограммы в документах.

См. Процентили (как правило) приблизительны, Сжатие и Подсказка выполнения для рекомендаций по поводу приближения, производительности и использования памяти при агрегации процентильных рангов

Процентильный ранг показывает процент наблюдаемых значений, которые меньше или равны определённому значению. Например, если значение больше или равно 95% наблюдаемых значений, считается, что оно находится на 95-м процентильном ранге.

Предположим, ваши данные представляют время загрузки веб-сайта. У вас может быть соглашение об уровне сервиса, что 95% загрузок страниц завершаются в течение 500 мс, а 99% - в течение 600 мс.

Рассмотрим ряд процентилей, представляющих время загрузки:

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_ranks": {
            "percentile_ranks": {
                "field": "load_time",
                "values": [
                    500,
                    600
                ]
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_ranks: {
        percentile_ranks: {
          field: 'load_time',
          values: [
            500,
            600
          ]
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_ranks: {
      percentile_ranks: {
        field: "load_time",
        values: [500, 600],
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "field": "load_time",   
        "values": [ 500, 600 ]
      }
    }
  }
}

Поле load_time должно быть числовым полем

Ответ будет выглядеть следующим образом:

{
  ...

 "aggregations": {
    "load_time_ranks": {
      "values": {
        "500.0": 55.0,
        "600.0": 64.0
      }
    }
  }
}

Из этой информации вы можете определить, что вы достигаете целевого времени загрузки на 99%, но не совсем достигаете целевого времени загрузки на 95%.

Ключевой ответ

По умолчанию флаг keyed установлен на true, что связывает уникальный строковый ключ с каждым ведром и возвращает диапазоны в виде хеша, а не массива. Установка флага keyed на false отключит это поведение:

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_ranks": {
            "percentile_ranks": {
                "field": "load_time",
                "values": [
                    500,
                    600
                ],
                "keyed": False
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_ranks: {
        percentile_ranks: {
          field: 'load_time',
          values: [
            500,
            600
          ],
          keyed: false
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_ranks: {
      percentile_ranks: {
        field: "load_time",
        values: [500, 600],
        keyed: false,
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "field": "load_time",
        "values": [ 500, 600 ],
        "keyed": false
      }
    }
  }
}

Ответ:

{
  ...

  "aggregations": {
    "load_time_ranks": {
      "values": [
        {
          "key": 500.0,
          "value": 55.0
        },
        {
          "key": 600.0,
          "value": 64.0
        }
      ]
    }
  }
}

Скрипт

Если вам нужно выполнить агрегацию по значениям, которые не индексированы, используйте динамическое поле. Например, если наше время загрузки измеряется в миллисекундах, но мы хотим рассчитать процентили в секундах:

resp = client.search(
    index="latency",
    size=0,
    runtime_mappings={
        "load_time.seconds": {
            "type": "long",
            "script": {
                "source": "emit(doc['load_time'].value / params.timeUnit)",
                "params": {
                    "timeUnit": 1000
                }
            }
        }
    },
    aggs={
        "load_time_ranks": {
            "percentile_ranks": {
                "values": [
                    500,
                    600
                ],
                "field": "load_time.seconds"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    runtime_mappings: {
      'load_time.seconds' => {
        type: 'long',
        script: {
          source: "emit(doc['load_time'].value / params.timeUnit)",
          params: {
            "timeUnit": 1000
          }
        }
      }
    },
    aggregations: {
      load_time_ranks: {
        percentile_ranks: {
          values: [
            500,
            600
          ],
          field: 'load_time.seconds'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  runtime_mappings: {
    "load_time.seconds": {
      type: "long",
      script: {
        source: "emit(doc['load_time'].value / params.timeUnit)",
        params: {
          timeUnit: 1000,
        },
      },
    },
  },
  aggs: {
    load_time_ranks: {
      percentile_ranks: {
        values: [500, 600],
        field: "load_time.seconds",
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "runtime_mappings": {
    "load_time.seconds": {
      "type": "long",
      "script": {
        "source": "emit(doc['load_time'].value / params.timeUnit)",
        "params": {
          "timeUnit": 1000
        }
      }
    }
  },
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "values": [ 500, 600 ],
        "field": "load_time.seconds"
      }
    }
  }
}

HDR Гистограмма

HDR Гистограмма (гистограмма высокой динамической области) - это альтернативная реализация, которая может быть полезной при вычислении процентильных рангов для измерений задержки, поскольку она может быть быстрее, чем реализация t-digest, с компромиссом в виде большего объёма памяти. Эта реализация поддерживает фиксированную наихудшую процентную погрешность (указанную как количество значащих цифр). Это означает, что если данные записываются со значениями от 1 микросекунды до 1 часа (3 600 000 000 микросекунд) в гистограмме с настройками на 3 значащих цифры, она будет поддерживать разрешение в 1 микросекунду для значений до 1 миллисекунды и 3,6 секунды (или лучше) для максимального отслеживаемого значения (1 час).

HDR Гистограмма может быть использована путём указания объекта hdr в запросе:

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_ranks": {
            "percentile_ranks": {
                "field": "load_time",
                "values": [
                    500,
                    600
                ],
                "hdr": {
                    "number_of_significant_value_digits": 3
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_ranks: {
        percentile_ranks: {
          field: 'load_time',
          values: [
            500,
            600
          ],
          hdr: {
            number_of_significant_value_digits: 3
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_ranks: {
      percentile_ranks: {
        field: "load_time",
        values: [500, 600],
        hdr: {
          number_of_significant_value_digits: 3,
        },
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "field": "load_time",
        "values": [ 500, 600 ],
        "hdr": {                                  
          "number_of_significant_value_digits": 3 
        }
      }
    }
  }
}

Объект hdr указывает, что для расчёта процентилей должна быть использована HDR Гистограмма, и конкретные настройки для этого алгоритма могут быть указаны внутри объекта

number_of_significant_value_digits указывает разрешение значений для гистограммы в виде количества значащих цифр

HDR Гистограмма поддерживает только положительные значения и выдаст ошибку, если ей будет передано отрицательное значение. Также не рекомендуется использовать HDR Гистограмму, если диапазон значений неизвестен, так как это может привести к высокому потреблению памяти.

Пропущенное значение

Параметр missing определяет, как должны обрабатываться документы, у которых отсутствует значение. По умолчанию они будут игнорироваться, но также можно обработать их так, как будто у них есть значение.

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_ranks": {
            "percentile_ranks": {
                "field": "load_time",
                "values": [
                    500,
                    600
                ],
                "missing": 10
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_ranks: {
        percentile_ranks: {
          field: 'load_time',
          values: [
            500,
            600
          ],
          missing: 10
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_ranks: {
      percentile_ranks: {
        field: "load_time",
        values: [500, 600],
        missing: 10,
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "field": "load_time",
        "values": [ 500, 600 ],
        "missing": 10           
      }
    }
  }
}

Документы без значения в поле load_time попадут в ту же группу, что и документы, у которых есть значение 10.

© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/search-aggregations-metrics-percentile-rank-aggregation.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API