Агрегирование перцентилей
Метрическое агрегирование, которое вычисляет одну или несколько перцентилей по числовым значениям, извлечённым из агрегируемых документов. Эти значения могут быть извлечены из конкретных числовых или исторических полей в документах.
Перцентили показывают точку, в которой находится определённый процент наблюдаемых значений. Например, 95-й перцентиль — это значение, которое больше 95 % наблюдаемых значений.
Перцентили часто используются для поиска выбросов. В нормальных распределениях 0,13-й и 99,87-й перцентили представляют собой три стандартных отклонения от среднего. Любые данные, которые выходят за пределы трёх стандартных отклонений, часто считаются аномалиями.
Если запрашивается диапазон перцентилей, то они могут быть использованы для оценки распределения данных и определения того, является ли распределение данных смещённым, бимодальным и т. д.
Предположим, ваши данные представляют собой время загрузки веб-страниц. Среднее и медианное время загрузки не слишком полезны администратору. Максимальное значение может быть интересным, но оно легко искажается единственным медленным ответом.
Давайте рассмотрим диапазон перцентилей, представляющих время загрузки:
GET latency/_search
{
"size": 0,
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "load_time"
}
}
}
} | Поле |
По умолчанию метрика percentile сгенерирует диапазон перцентилей: [ 1, 5, 25, 50, 75, 95, 99 ]. Ответ будет выглядеть так:
{
...
"aggregations": {
"load_time_outlier": {
"values": {
"1.0": 5.0,
"5.0": 25.0,
"25.0": 165.0,
"50.0": 445.0,
"75.0": 725.0,
"95.0": 945.0,
"99.0": 985.0
}
}
}
} Как вы можете видеть, агрегирование вернёт вычисленное значение для каждой перцентили в стандартном диапазоне. Если мы предполагаем, что время отклика измеряется в миллисекундах, сразу становится очевидно, что веб-страница обычно загружается за 10-725 мс, но иногда время загрузки скачет до 945-985 мс.
Часто администраторы интересуются только выбросами — крайними перцентилями. Мы можем указать только те проценты, которые нас интересуют (запрашиваемые перцентили должны быть значениями от 0 до 100 включительно):
GET latency/_search
{
"size": 0,
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "load_time",
"percents": [ 95, 99, 99.9 ]
}
}
}
} | Используйте параметр |
Ответ с ключами
По умолчанию флаг keyed установлен в значение true, что связывает уникальный строковый ключ с каждым бакетом и возвращает диапазоны в виде хеша, а не массива. Установка флага keyed в значение false отключит это поведение:
GET latency/_search
{
"size": 0,
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "load_time",
"keyed": false
}
}
}
} Ответ:
{
...
"aggregations": {
"load_time_outlier": {
"values": [
{
"key": 1.0,
"value": 5.0
},
{
"key": 5.0,
"value": 25.0
},
{
"key": 25.0,
"value": 165.0
},
{
"key": 50.0,
"value": 445.0
},
{
"key": 75.0,
"value": 725.0
},
{
"key": 95.0,
"value": 945.0
},
{
"key": 99.0,
"value": 985.0
}
]
}
}
} Сценарий
Если вам нужно выполнить агрегирование по значениям, которые не индексированы, используйте динамическое поле. Например, если наше время загрузки измеряется в миллисекундах, но вы хотите, чтобы перцентили вычислялись в секундах:
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_outlier": {
"percentiles": {
"field": "load_time.seconds"
}
}
}
} Перцентили (обычно) являются приблизительными
Существует множество различных алгоритмов вычисления перцентилей. Примитивный алгоритм просто хранит все значения в отсортированном массиве. Чтобы найти 50-й перцентиль, вы просто находите значение, которое находится на позиции my_array[count(my_array) * 0.5].
Очевидно, что примитивный алгоритм не масштабируется — отсортированный массив растёт линейно с числом значений в наборе данных. Для вычисления перцентилей по потенциально миллиардам значений в кластере Elasticsearch вычисляются приблизительные перцентили.
Алгоритм, используемый метрикой percentile, называется TDigest (представленный Тедом Даннингом в Computing Accurate Quantiles using T-Digests).
При использовании этой метрики необходимо учитывать несколько рекомендаций:
- Точность пропорциональна
q(1-q). Это означает, что крайние перцентили (например, 99 %) более точные, чем менее крайние перцентили, такие как медиана. - Для небольших наборов значений перцентили очень точны (и потенциально 100 % точны, если данные достаточно малы).
- По мере увеличения количества значений в бакете алгоритм начинает приближать перцентили. По существу, он жертвует точностью ради экономии памяти. Точный уровень неточности трудно обобщить, так как он зависит от распределения данных и объёма агрегируемых данных.
На следующем графике показана относительная ошибка при равномерном распределении в зависимости от количества собранных значений и запрашиваемой перцентили:
Он показывает, как точность лучше для крайних перцентилей. Причина, по которой ошибка уменьшается для большого числа значений, заключается в том, что закон больших чисел делает распределение значений всё более однородным, и дерево t-digest может лучше его обобщить. Это не будет иметь места при более смещённых распределениях.
Агрегирования перцентилей также являются недетерминированными. Это означает, что вы можете получить немного разные результаты, используя одни и те же данные.
Сжатие
Приблизительные алгоритмы должны балансировать использование памяти и точность оценки. Этот баланс можно контролировать с помощью параметра compression:
GET latency/_search
{
"size": 0,
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "load_time",
"tdigest": {
"compression": 200
}
}
}
}
} | Сжатие контролирует использование памяти и погрешность приближения. |
Алгоритм TDigest использует несколько «узлов» для приближения перцентилей — чем больше узлов доступно, тем выше точность (и больший объём памяти), пропорционально объёму данных. Параметр compression ограничивает максимальное число узлов до 20 * compression.
Следовательно, увеличивая значение сжатия, вы можете повысить точность перцентилей за счёт увеличения использования памяти. Более высокие значения сжатия также замедляет алгоритм, так как размер базовой структуры данных дерева увеличивается, что приводит к более дорогим операциям. Значение сжатия по умолчанию равно 100.
Один «узел» использует примерно 32 байта памяти, поэтому в худшем случае (большой объём данных, поступающий отсортированным и упорядоченно) значения по умолчанию создадут TDigest размером примерно 64 КБ. На практике данные обычно более случайны, и TDigest использует меньше памяти.
HDR Гистограмма
HDR Гистограмма (гистограмма с высоким динамическим диапазоном) — это альтернативная реализация, которая может быть полезна при вычислении перцентилей для измерений задержки, так как она может быть быстрее, чем реализация t-digest, с trade-off увеличения потребления памяти. Эта реализация поддерживает фиксированную процентную погрешность худшего случая (указанную как количество значащих цифр). Это означает, что если данные регистрируются со значениями от 1 микросекунды до 1 часа (3 600 000 000 микросекунд) в гистограмме, настроенной на 3 значащих цифры, она будет поддерживать разрешение 1 микросекунда для значений до 1 миллисекунды и 3,6 секунды (или лучше) для максимального отслеживаемого значения (1 час).
HDR Гистограмма может быть использована, указав параметр method в запросе:
GET latency/_search
{
"size": 0,
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "load_time",
"percents": [ 95, 99, 99.9 ],
"hdr": {
"number_of_significant_value_digits": 3
}
}
}
}
} | Объект | |
|
|
HDR Гистограмма поддерживает только положительные значения и вернёт ошибку, если ей передать отрицательное значение. Также не рекомендуется использовать HDR Гистограмму, если диапазон значений неизвестен, так как это может привести к высокому потреблению памяти.
Пропущенное значение
Параметр missing определяет, как должны обрабатываться документы, в которых отсутствует значение. По умолчанию они игнорируются, но также их можно обрабатывать так, как будто у них есть значение.
GET latency/_search
{
"size": 0,
"aggs": {
"grade_percentiles": {
"percentiles": {
"field": "grade",
"missing": 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/7.17/search-aggregations-metrics-percentile-aggregation.html