Оптимізація Elasticsearch-індексів для 1С-Бітрікс
Оптимізація індексів Elasticsearch під каталог і пошук Бітрікс
Elasticsearch працює «з коробки» — до першого серйозного навантаження. На каталозі в 100 000+ товарів з активною переіндексацією через синхронізацію з 1С типові симптоми деградації: heap memory постійно під 80%, GC паузи по 200–500 мс, search latency зростає до 2–5 секунд, merge throttling блокує індексацію.
Оптимізація індексів ES — це робота з кількома рівнями: налаштування шардування, merge policy, fielddata та doc values, refresh interval, force merge для завершених індексів.
Діагностика стану кластера та індексів
Починаємо з оцінки здоров'я:
# Стан кластера
GET /_cluster/health?pretty
# Статистика індексів
GET /bitrix_catalog/_stats?pretty
# Гарячі потоки (що навантажує CPU)
GET /_nodes/hot_threads
# Використання пам'яті
GET /_nodes/stats/jvm?pretty
Ключові метрики для діагностики:
-
jvm.mem.heap_used_percent— якщо стабільно >75%, потрібно або збільшити heap, або зменшити fielddata -
indices.segments.count— велика кількість сегментів уповільнює пошук; ознака неоптимального merge -
indices.merges.current_size_in_bytes— активний merge у продакшні під час пікового навантаження
Налаштування шардування
Найпоширеніша помилка — занадто багато шардів. Кожен шард — це Lucene-індекс з overhead по пам'яті близько 50 МБ на heap. 100 шардів = 5 ГБ heap лише на метадані.
Для каталогу Бітрікс правило: 1 шард на кожні 20–40 ГБ даних, не більше 3–5 шардів для типового магазину:
PUT /bitrix_catalog
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
Змінити кількість primary shards після створення індексу не можна — потрібно створити новий індекс і переіндексувати через Reindex API. Плануємо правильно з першого разу.
Оптимізація refresh interval
За замовчуванням ES оновлює індекс кожну секунду — нові документи стають доступні для пошуку через 1 с. Це дорого при масовій індексації:
PUT /bitrix_catalog/_settings
{
"index": {
"refresh_interval": "30s"
}
}
Під час синхронізації з 1С (bulk indexing) взагалі вимикаємо refresh:
{ "index": { "refresh_interval": "-1" } }
Після завершення — відновлюємо та викликаємо POST /bitrix_catalog/_refresh вручну.
Оптимізація merge policy
PUT /bitrix_catalog/_settings
{
"index.merge.policy.max_merged_segment": "5gb",
"index.merge.policy.segments_per_tier": 10,
"index.merge.scheduler.max_thread_count": 1
}
max_thread_count: 1 для HDD-серверів — merge на кількох потоках вбиває I/O. На NVMe можна ставити 2–4.
Оптимізація fielddata та doc values
Fielddata завантажується в heap при агрегаціях і сортуванні за text-полями. Для фасетних фільтрів каталогу використовуємо виключно keyword із doc values (зберігаються на диску, не в heap):
PUT /bitrix_catalog/_mapping
{
"properties": {
"brand": {
"type": "keyword",
"doc_values": true,
"eager_global_ordinals": true
}
}
}
eager_global_ordinals: true для висококардинальних полів фільтра (бренд, категорія) — будує ordinals при refresh, а не при першому запиті агрегації. Усуває «холодний старт» після нічної переіндексації.
Force merge для статичних індексів
Якщо каталог змінюється вночі (синхронізація з 1С раз на добу), денний індекс можна змерджити в один сегмент:
POST /bitrix_catalog/_forcemerge?max_num_segments=1
Операція важка, запускаємо лише у технічне вікно. Один сегмент = максимальна швидкість пошуку, мінімальний overhead.
Налаштування індексування з Бітрікс
На стороні PHP при пакетній індексації використовуємо Bulk API з оптимальним розміром пачки:
$batchSize = 500; // оптимум для товарів з описом
$body = [];
foreach ($products as $product) {
$body[] = ['index' => ['_index' => 'bitrix_catalog', '_id' => $product['ID']]];
$body[] = $this->prepareDocument($product);
}
$client->bulk(['body' => $body]);
Розмір пачки підбираємо емпірично: занадто маленький — багато round-trips, занадто великий — GC pressure. Зазвичай 200–500 документів для товарів з описами.
Моніторинг після оптимізації
Підключаємо метрики ES у Prometheus через elasticsearch_exporter та сповіщаємо при:
- heap_used_percent > 80% протягом 5+ хвилин
- GC time > 1 секунда за 1 хвилину
- search latency p99 > 500 мс
- unassigned shards > 0
Результат
Комплексна оптимізація індексів знижує heap utilization на 30–50%, усуває GC паузи при нормальному навантаженні, скорочує час пошукового запиту з 1–3 с до 50–150 мс, прискорює нічну переіндексацію каталогу в 3–5 разів.







