Типичные ошибки: text/keyword, mapping explosion, тяжёлые агрегации
Собираем главные грабли Elasticsearch в один урок, чтобы вы наступали на них в учебнике, а не на проде.
Большинство проблем с ES сводятся к трём причинам: неверный тип поля, неконтролируемый рост маппинга и слишком тяжёлые агрегации.
Ошибка 1: путаница text и keyword
Самая частая ошибка новичков. Признаки беды:
- «Поиск ничего не находит». Обычно это
termпо полюtext(значение в индексе — проанализированный терм, а term ищет буквально) — мы разбирали это в уроке про match/term. - «Не получается отсортировать/сгруппировать». Сортировка и
terms-агрегация по анализируемомуtextне работают (ошибка про fielddata).
Решение — multi-field: индексировать поле и как text (для поиска), и как keyword (для точных операций):
{
"mappings": {
"properties": {
"category": {
"type": "text",
"fields": {
"raw": { "type": "keyword" }
}
}
}
}
}Тогда поиск идёт по category, а группировка и сортировка — по category.raw. Это стандартная практика.
Ошибка 2: mapping explosion
Динамический маппинг удобен, но опасен: если в документах появляются всё новые поля (например, ключи приходят из пользовательских данных или из имён метрик), маппинг разрастается до тысяч полей. Каждое поле — это память и накладные расходы; при тысячах полей кластер деградирует и может упасть. Это и есть mapping explosion.
Защита:
- задавать маппинг явно и не плодить поля;
- отключать динамику там, где она не нужна:
"dynamic": "strict"(новое поле — ошибка) или"dynamic": false(поле игнорируется в индексе); - не превращать произвольные ключи данных в имена полей; хранить такие пары как
flattenedили массив объектов{key, value}.
Ошибка 3: тяжёлые агрегации
Агрегации мощные, но дорогие. Что бьёт по кластеру:
- Высокая кардинальность.
termsпо полю с миллионами уникальных значений (id пользователей) строит огромное число бакетов и ест память. - Глубокая вложенность. Агрегации в агрегациях множат число корзин комбинаторно.
- Большой временной диапазон + мелкий интервал.
date_histogramпо минутам за год — миллионы бакетов.
Лечится сужением диапазона (фильтром по дате), разумным size у terms, и пониманием, что точный подсчёт уникальных дорог — для прикидки есть cardinality (приблизительная, но дешёвая).
Как работает под капотом
Все три ошибки — про ресурсы. Тип поля определяет, какие структуры строятся: text даёт инвертированный индекс (поиск), но не doc values для сортировки; keyword — наоборот. Маппинг целиком держится в памяти кластера (cluster state) и рассылается между узлами — поэтому тысячи полей его раздувают и замедляют управление кластером. Агрегации считаются в памяти на каждом шарде: число бакетов напрямую определяет потребление памяти, и при взрывном росте узел упирается в circuit breaker или падает по OOM.
Частые ошибки
- Не закладывать keyword-подполе сразу. Потом окажется, что по полю нельзя сортировать/группировать, и придётся переиндексировать.
- Оставлять dynamic по умолчанию на пользовательских данных. Прямой путь к mapping explosion.
- Агрегировать «всё и сразу». Всегда ограничивайте диапазон фильтром и кардинальность параметром
size.
Итоги
- text для поиска, keyword для точных операций; используйте multi-field, чтобы иметь и то, и другое.
- Mapping explosion от динамических полей рушит кластер — задавайте маппинг явно и ограничивайте динамику.
- Тяжёлые агрегации (высокая кардинальность, глубокая вложенность, мелкие интервалы) едят память — сужайте диапазон и size.