Оптимизация переиндексации Elasticsearch для 1С-Битрикс
Оптимизация переиндексации Elasticsearch для 1С-Битрикс
На проекте с 800 000 SKU плановая переиндексация из 1С занимала 14 часов. За это время накапливалась очередь изменений, поиск отдавал устаревшие данные, а импорт из 1С конкурировал с переиндексацией за ресурсы. Задача — сократить полную переиндексацию до 1–2 часов без остановки поиска.
Почему переиндексация тормозит
Типичные причины медленной переиндексации:
Последовательная индексация через одиночные запросы. Каждый документ отправляется отдельным PUT /bitrix_catalog/_doc/{id}. HTTP-накладные расходы, TCP-соединение на каждый запрос, ответ 200ms * 800000 = 160000 секунд.
Слишком маленький batch в Bulk API. Размер пакета 10 документов вместо оптимальных 200–1000.
Refresh после каждого пакета. Принудительный POST /bitrix_catalog/_refresh после каждого batch — самоубийство производительности. Refresh создаёт новый сегмент Lucene, блокирует индексацию на десятки миллисекунд.
Неправильный refresh_interval во время переиндексации. Дефолтные 1 секунда генерируют сотни тысяч мелких сегментов, которые ES тратит силы на merge.
Стратегия zero-downtime переиндексации
Ключевой приём — индексировать в новый индекс, а не поверх рабочего:
Текущий: bitrix_catalog_v1 <-- алиас bitrix_catalog
Новый: bitrix_catalog_v2 <-- индексируем сюда
После: переключаем алиас на v2
// Создаём алиас при начальной настройке
POST /_aliases
{
"actions": [
{ "add": { "index": "bitrix_catalog_v1", "alias": "bitrix_catalog" } }
]
}
Битрикс работает с алиасом bitrix_catalog. Пока идёт переиндексация в v2, поиск продолжает работать через v1. После завершения атомарно переключаем алиас.
Настройка Elasticsearch для быстрой индексации
Перед переиндексацией временно меняем настройки через API:
PUT /bitrix_catalog_v2/_settings
{
"index": {
"refresh_interval": "-1",
"number_of_replicas": 0,
"translog.durability": "async",
"translog.sync_interval": "30s"
}
}
refresh_interval: -1 полностью отключает автоматический refresh — документы не попадают в поиск до явного refresh, зато индексация ускоряется в 3–5 раз.
number_of_replicas: 0 отключает репликацию на время индексации. ES не тратит время на копирование шардов.
translog.durability: async — транслог сбрасывается на диск не при каждой операции, а по таймеру. Риск потери данных при сбое за последние 30 секунд — приемлемо для переиндексации, не для продакшн-данных.
После завершения восстанавливаем настройки:
PUT /bitrix_catalog_v2/_settings
{
"index": {
"refresh_interval": "5s",
"number_of_replicas": 1,
"translog.durability": "request"
}
}
Затем принудительный merge для уменьшения числа сегментов:
POST /bitrix_catalog_v2/_forcemerge?max_num_segments=1
Оптимизация PHP-индексатора
Размер пакета для Bulk API подбираем эмпирически. Ориентир — 5–15 МБ на один запрос:
$batchSize = 500; // документов на один bulk-запрос
$bulk = [];
foreach ($products as $product) {
$bulk[] = ['index' => ['_index' => 'bitrix_catalog_v2', '_id' => $product['ID']]];
$bulk[] = buildDocument($product);
if (count($bulk) >= $batchSize * 2) {
$client->bulk(['body' => $bulk]);
$bulk = [];
// НЕ вызываем _refresh здесь
}
}
if (!empty($bulk)) {
$client->bulk(['body' => $bulk]);
}
Параллельная индексация через несколько процессов — делим каталог по диапазонам ID:
# Процесс 1: ID 1 - 200000
php index_products.php --from=1 --to=200000 &
# Процесс 2: ID 200001 - 400000
php index_products.php --from=200001 --to=400000 &
# Процесс 3: ID 400001 - 600000
php index_products.php --from=400001 --to=600000 &
wait
echo "Indexing complete"
Три параллельных процесса на 3-нодовом кластере дают линейное ускорение. Ограничение — пропускная способность MySQL при чтении данных.
Переключение алиаса
После завершения индексации атомарно переключаем алиас:
POST /_aliases
{
"actions": [
{ "remove": { "index": "bitrix_catalog_v1", "alias": "bitrix_catalog" } },
{ "add": { "index": "bitrix_catalog_v2", "alias": "bitrix_catalog" } }
]
}
Операция атомарна — между удалением старого алиаса и добавлением нового нет момента, когда алиас не существует. Переключение занимает миллисекунды, поиск не прерывается.
Результат
На каталоге 800к SKU после оптимизации: полная переиндексация 1 ч 20 мин (было 14 ч), инкрементальное обновление 200–300 документов в секунду через Bulk API вместо 15–20 через одиночные запросы.







