Оптимізація пошукової індексації 1С-Бітрікс
Оптимізація пошукової індексації вбудованого модуля Бітрікс
Вбудований пошук Бітрікс працює через таблиці b_search_content, b_search_content_stem, b_search_stem. На каталозі в 30 000+ товарів повна переіндексація займає 4–12 годин, агент CSearchIndex::IndexAgent безперервно крутиться на сервері, а якість пошуку при цьому залишається посередньою: стемінг не справляється з морфологією, релевантність не враховує популярність і продажі.
Завдання оптимізації пошукової індексації вирішується на двох рівнях: тактичному (прискорити та стабілізувати існуючий механізм) і стратегічному (перейти на Elasticsearch при необхідності повнотекстового пошуку з фасетами).
Діагностика поточної індексації
Дивимось стан індексних таблиць:
-- Розмір таблиць пошуку
SELECT
table_name,
ROUND(data_length / 1024 / 1024, 2) AS data_mb,
ROUND(index_length / 1024 / 1024, 2) AS index_mb,
table_rows
FROM information_schema.TABLES
WHERE table_schema = DATABASE()
AND table_name LIKE 'b_search%'
ORDER BY data_length DESC;
Таблиця b_search_content_stem на великому порталі може займати 2–5 ГБ. OPTIMIZE TABLE для неї займає години та блокує інші запити — виконуємо лише у технічне вікно.
Перевіряємо прогрес поточної індексації:
SELECT SITE_ID, MODULE_ID, PARAM1,
COUNT(*) as indexed_count,
MAX(DATE_CHANGE) as last_indexed
FROM b_search_content
GROUP BY SITE_ID, MODULE_ID, PARAM1;
Оптимізація параметрів індексації
В адміністративному інтерфейсі (Налаштування → Пошук → Налаштування):
Мінімальна довжина слова: збільшуємо з 2 до 3–4. Дволітерні слова засмічують індекс і не несуть пошукового змісту в більшості запитів.
Стоп-слова: додаємо прийменники, сполучники, артиклі. Для україномовного/російськомовного сайту базовий список включає 50–80 слів.
Модулі, що індексуються: вимикаємо індексацію модулів, пошук за якими не потрібен користувачам (форуми, якщо закриті; блоги; документообіг). Кожний зайвий модуль в індексі збільшує обсяг таблиць і час переіндексації.
Кількість елементів за один прохід агента:
// У налаштуваннях модуля пошуку або через агент
CSearch::ReIndex($moduleId, $start, $finish, $step = 50);
Оптимальне значення кроку — 50–100 елементів. Більше — агент працює довше одного запуску і може бути перерваний PHP timeout. Менше — занадто багато накладних витрат на запуск.
Інкрементальна vs повна індексація
Повна переіндексація (ReIndexAll) — лише при первинному налаштуванні або після серйозних змін структури каталогу. У робочому режимі має працювати інкрементальна індексація через агент.
Агент CSearchIndex::IndexAgent працює інкрементально — індексує елементи, змінені з моменту останньої індексації. Проблема виникає, коли DATE_CHANGE у елементів оновлюється при кожній синхронізації з 1С (навіть якщо контент не змінився). В цьому випадку агент фактично переіндексує весь каталог при кожній синхронізації.
Рішення: в обробнику імпорту з 1С порівнюємо хеш значущих полів до і після оновлення, оновлюємо DATE_CHANGE лише при реальній зміні контенту:
$oldHash = md5($oldElement['NAME'] . $oldElement['DETAIL_TEXT'] . implode(',', $oldProperties));
$newHash = md5($newElement['NAME'] . $newElement['DETAIL_TEXT'] . implode(',', $newProperties));
if ($oldHash !== $newHash) {
// Оновлюємо зі зміною DATE_CHANGE
} else {
// Оновлюємо залишки/ціни без тригера переіндексації
$DB->Query("UPDATE b_iblock_element SET TIMESTAMP_X = TIMESTAMP_X WHERE ID = {$id}");
}
Налаштування FULLTEXT-індексів MySQL
Вбудований пошук Бітрікс використовує FULLTEXT-індекси MySQL для таблиці b_search_content:
# У my.cnf для InnoDB FULLTEXT
innodb_ft_min_token_size = 3
innodb_ft_stopword_table = 'mydb/my_stopwords'
ft_query_expansion_limit = 20
Після зміни ft_min_token_size потрібна повна переіндексація FULLTEXT (OPTIMIZE TABLE b_search_content) — плануємо у технічне вікно.
Очищення застарілих записів індексу
На живих сайтах у b_search_content накопичуються записи видалених елементів — «сміття», яке збільшує розмір індексу та уповільнює пошук:
-- Знайти записи видалених елементів інфоблоку
SELECT sc.ID, sc.PARAM1, sc.PARAM2
FROM b_search_content sc
LEFT JOIN b_iblock_element ie ON ie.ID = CAST(sc.PARAM1 AS UNSIGNED)
WHERE sc.MODULE_ID = 'iblock'
AND ie.ID IS NULL
LIMIT 10000;
Видаляємо пакетами по 1000 записів через агент або cron-скрипт — одним DELETE на 100 000 записів у prod не працюємо.
Моніторинг якості пошуку
Після оптимізації налаштовуємо логування пошукових запитів з нульовою видачею:
SELECT QUERY, SITE_ID, RESULT_COUNT, DATE_SEARCH
FROM b_search_log
WHERE RESULT_COUNT = 0
ORDER BY DATE_SEARCH DESC
LIMIT 100;
Запити з нульовою видачею — сигнал до розширення контенту, додавання синонімів або переходу на морфологічний пошук.
Перехід на Elasticsearch
Якщо вбудований пошук не справляється з вимогами щодо якості або продуктивності — переходимо на Elasticsearch через модуль intec.search або кастомну інтеграцію. Це окрема послуга, але діагностику та рекомендації проводимо в рамках даної роботи.
Результат
Оптимізація параметрів і інкрементальної стратегії індексації скорочує час повного обходу каталогу на 50–80%, знижує навантаження агента до рівня, що не впливає на основні запити, і покращує якість пошукової видачі завдяки налаштуванню стоп-слів та мінімальної довжини токена.







