Оптимизация поисковой индексации 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%, снижает нагрузку агента до уровня, не влияющего на основные запросы, и улучшает качество поисковой выдачи за счёт настройки стоп-слов и минимальной длины токена.







