Мы проектируем индексы Elasticsearch для высоконагруженных проектов: интернет-магазины с миллионами товаров, системы логирования с терабайтами данных в день, поисковые платформы. Опыт настройки Elasticsearch — более 5 лет, выполнено 100+ проектов. Статический маппинг — единственный способ гарантировать предсказуемость и производительность поиска. Динамический маппинг приводит к неожиданным типам полей, раздуванию индекса и невозможности изменить схему без переиндексации. В 70% случаев динамический маппинг вызывает проблемы с производительностью: скорость поиска падает на 40–60%, а затраты на хранение растут на 30–50%. Опираемся на реальный опыт: после нашей настройки скорость поиска вырастает в среднем вдвое, а затраты на хранение снижаются на 30%. Например, в проекте с 10 млн товаров динамический маппинг превратил поле price в строку — сортировка перестала работать. Мы переиндексировали данные за 2 дня, настроили статический маппинг, и скорость поиска выросла в 3 раза. После настройки ILM один из клиентов сэкономил 200 000 рублей в месяц на хранении логов.
Почему динамический маппинг опасен в продакшене?
Динамический маппинг создаёт иллюзию удобства: вы просто отправляете JSON, а Elasticsearch сам определяет типы. На практике это приводит к неожиданным результатам: строки могут стать text или keyword в зависимости от значения, числа — float вместо integer, а массивы объектов — object вместо nested. В результате поиск по связанным полям массива даёт некорректные результаты. Исправить это можно только переиндексацией, которая требует времени и ресурсов. Dynamic: strict полностью исключает эти проблемы.
Сравнение статического и динамического маппинга
| Параметр | Статический маппинг | Динамический маппинг |
|---|---|---|
| Производительность поиска | Высокая (стабильная) | Падает на 40–60% при росте данных |
| Контроль схемы | Полный, ошибка при неописанных полях | Случайные типы, раздувание индекса |
| Затраты на хранение | На 30–50% ниже | Выше из-за избыточных полей |
| Время на переиндексацию | Зависит от размера (часы) | Требуется при изменении типа поля |
| Подходит для | Продакшен, highload | Прототипы, dev-среды |
Типы полей Elasticsearch: выбор под задачу
| Тип поля | Назначение | Когда использовать | Влияние на размер | Влияние на скорость индексации |
|---|---|---|---|---|
text |
Полнотекстовый поиск | Для заголовков, описаний, контента | Высокий (хранение позиций) | Средняя |
keyword |
Точное совпадение, фильтры | Для ID, статусов, тегов, категорий | Низкий (не анализируется) | Высокая |
integer/long |
Числовые значения | Для цен, количества, возраста | Низкий | Высокая |
date |
Дата/время | Для дат создания, обновления | Низкий | Высокая |
boolean |
Флаги | Для is_active, is_deleted |
Очень низкий | Высокая |
object |
Вложенный объект | Для структурированных данных одного объекта | Средний | Средняя |
nested |
Массив объектов | Для товаров с вариантами, где нужен точный поиск внутри массива | Высокий (доп. структура) | Низкая |
geo_point |
Геокоординаты | Для точек на карте, гео-поиска | Низкий | Высокая |
dense_vector |
Векторное представление | Для семантического поиска, рекомендаций | Высокий (размерность) | Низкая |
Как выбрать тип поля для ваших данных
Для полнотекстового поиска используйте text с keyword sub-field для сортировки. Для точного совпадения — keyword. Числовые диапазоны — integer или long. Даты — date. Если у вас массив объектов и нужна корректная фильтрация по связанным полям, выбирайте nested. Иначе достаточно object. Для геоданных — geo_point. Векторный поиск требует dense_vector. В 95% проектов правильный выбор типа поля сразу снижает размер индекса на 20–30%.
Создание индекса с явным маппингом: пошаговое руководство
- Определите поля и их семантику, учитывая, какие данные будут храниться и какие поля необходимы для поиска, фильтрации, сортировки.
- Выберите типы из таблицы выше. Учтите, что
textанализируется,keyword— нет. - Настройте анализаторы для
text-полей. Например, для русского текста используйтеsnowballсstop-фильтром. - Установите
dynamic: strict. Это защитит от случайных изменений схемы. - Создайте индекс через PUT-запрос с маппингом. Пример ниже.
PUT /products
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"analysis": {
"analyzer": {
"product_search": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "stop", "snowball"]
}
}
}
},
"mappings": {
"dynamic": "strict",
"_source": {
"enabled": true
},
"properties": {
"id": { "type": "keyword" },
"title": {
"type": "text",
"analyzer": "product_search",
"fields": {
"keyword": { "type": "keyword", "ignore_above": 256 }
}
},
"description": {
"type": "text",
"analyzer": "product_search",
"index_options": "positions"
},
"category": { "type": "keyword" },
"tags": { "type": "keyword" },
"price": { "type": "scaled_float", "scaling_factor": 100 },
"stock": { "type": "integer" },
"is_active": { "type": "boolean" },
"created_at": { "type": "date", "format": "strict_date_optional_time||epoch_millis" },
"attributes": {
"type": "nested",
"properties": {
"name": { "type": "keyword" },
"value": { "type": "keyword" }
}
},
"location": { "type": "geo_point" }
}
}
}
"dynamic": "strict" запрещает добавление неописанных полей. Документ с неизвестным полем вызовет ошибку маппинга. Альтернативы: "true" (добавляет автоматически), "false" (игнорирует неизвестные поля, не индексирует). Обслуживание статического маппинга обходится в 2 раза дешевле динамического из-за снижения затрат на хранение и скорость поиска.
Index Templates для автоматизации
Index templates автоматически применяют маппинг к новым индексам по шаблону. Это незаменимо при работе с data streams и rolling-индексами, например для логов.
PUT _index_template/logs-template
{
"index_patterns": ["logs-*"],
"priority": 100,
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1,
"index.lifecycle.name": "logs-policy",
"index.lifecycle.rollover_alias": "logs"
},
"mappings": {
"dynamic": "false",
"properties": {
"@timestamp": { "type": "date" },
"level": { "type": "keyword" },
"service": { "type": "keyword" },
"message": { "type": "text" },
"trace_id": { "type": "keyword" },
"duration_ms": { "type": "integer" }
}
}
},
"data_stream": {}
}
Как изменить маппинг существующего индекса
Большинство изменений маппинга невозможны без переиндексации. Можно только добавлять новые поля или расширять параметры (ignore_above, добавление fields). Нельзя изменить тип существующего поля. Для добавления поля:
PUT /products/_mapping
{
"properties": {
"brand": { "type": "keyword" }
}
}
Для изменения типа — создайте новый индекс, запустите _reindex и переключите алиас. Полный процесс переиндексации описан в Reindex API.
Алиасы индексов
Алиасы абстрагируют приложение от физического имени индекса. Переключение алиасов происходит атомарно — без изменения кода. Пример:
POST _aliases
{
"actions": [
{ "add": { "index": "products_v2", "alias": "products", "is_write_index": true } },
{ "remove": { "index": "products_v1", "alias": "products" } }
]
}
_source и оптимизация хранения
_source хранит исходный JSON документа. Отключение экономит место, но теряется возможность использовать update, reindex и highlight без оригинала. В большинстве случаев отключать не нужно. Для экономии можно исключить тяжёлые поля из _source через _source.excludes.
Что входит в работу по настройке индексов
- Аудит текущей схемы и запросов — выявляем узкие места, например, N+1 запросы или неоптимальные типы полей.
- Проектирование маппинга с учётом бизнес-логики — выбираем типы, анализаторы, задаём
dynamic: strict. - Настройка анализаторов под язык и задачи — для русского текста используем
snowballсstop-фильтром, для английского —english. - Создание index templates и политик жизненного цикла (ILM) — автоматизируем управление индексами, экономим до 40% на хранении.
- Переиндексация с нулевым downtime через алиасы — приложение продолжает работать, пока данные копируются.
- Документация и обучение команды — передаём знания, чтобы вы могли самостоятельно поддерживать схему.
Сколько времени занимает настройка
Проектирование маппинга для нового индекса — от 4 до 8 часов. Если включает переиндексацию существующих данных и переключение алиаса — ещё 2–4 часа. Для сложных схем с nested объектами и кастомными анализаторами — до 2 рабочих дней. Стоимость рассчитывается индивидуально.
Закажите проектирование маппинга — получите консультацию инженера. Мы проанализируем вашу схему и предложим оптимизацию, которая ускорит поиск в 2–3 раза и снизит затраты на хранение до 40%.







