Настройка полнотекстовых индексов MySQL для 1С-Битрикс

При разрастании каталога товаров в 1С-Битрикс до 200 тысяч элементов стандартный поиск перестаёт справляться — время отклика уходит за 10 секунд. На одном из проектов с каталогом на 500 тысяч товаров поиск через LIKE занимал до 18 секунд. После внедрения **FULLTEXT** с ngram-парсером время снизилось
Услуги, которые мы предлагаем
Показано 1 из 1Все 1626 услуг
Настройка полнотекстовых индексов MySQL для 1С-Битрикс
Простой
~1 день

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1415
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    995
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    733
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    863
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    772
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    1134

При разрастании каталога товаров в 1С-Битрикс до 200 тысяч элементов стандартный поиск перестаёт справляться — время отклика уходит за 10 секунд. На одном из проектов с каталогом на 500 тысяч товаров поиск через LIKE занимал до 18 секунд. После внедрения FULLTEXT с ngram-парсером время снизилось до 0.2 секунды. Мы провели аудит, настроили my.cnf, создали индексы и разработали кастомный компонент. Свяжитесь с нами для оценки вашего проекта.

Стандартный поиск Битрикс работает через компонент bitrix:search.page и модуль search. Он строит собственный индекс в таблице b_search_content — туда попадают все элементы инфоблоков, страницы, форумы. Поиск идёт через LIKE '%запрос%', что при объёме свыше 100 тысяч элементов превращается в table scan с деградацией до 5–15 секунд. Решение — полнотекстовые индексы MySQL (FULLTEXT) напрямую на таблицах инфоблоков или на b_search_content.

Как работает FULLTEXT в MySQL

FULLTEXT-индекс строится поверх текстовых колонок (CHAR, VARCHAR, TEXT). Запросы — через MATCH() AGAINST(). Два режима: IN NATURAL LANGUAGE MODE (ранжирование по релевантности) и IN BOOLEAN MODE (поддержка операторов: +обязательно, -исключить, *префикс).

Ограничения MySQL FULLTEXT:

  • Минимальная длина слова по умолчанию: innodb_ft_min_token_size = 3. Слова короче не индексируются.
  • Стоп-слова (innodb_ft_server_stopword_table) — их нужно отключить или перенастроить.
  • Для русского языка требуется правильная кодировка (utf8mb4) и, желательно, внешний парсер (ngram для InnoDB или Sphinx/Manticore как альтернатива).

Выбор парсера и архитектуры поиска

Ngram парсер для кириллицы

Стандартный FULLTEXT-парсер MySQL ориентирован на английский язык: минимальная длина слова 3 символа, стоп-слова. Кириллические слова часто короче (предлоги, союзы), поэтому они не индексируются. ngram парсер разбивает текст на биграммы (по 2 символа) и не зависит от языка. Это гарантирует, что любой запрос из двух и более символов найдёт соответствия. Настройка ngram_token_size=2 в my.cnf включает биграммный режим.

Использование FULLTEXT индексов

Если поиск нужен только по каталогу, эффективнее индексировать напрямую таблицы b_iblock_element (NAME, DETAIL_TEXT) и b_iblock_section (NAME). Это снижает нагрузку на b_search_content и упрощает архитектуру. Однако для общесайтового поиска удобнее использовать b_search_content — он включает все типы контента.

Настройка и создание индексов

Настройка my.cnf для русского FULLTEXT

[mysqld] innodb_ft_min_token_size = 2 innodb_ft_enable_stopword = OFF ngram_token_size = 2 

После изменения нужно пересоздать все FULLTEXT-индексы — просто перезапуска MySQL недостаточно.

создать FULLTEXT-индекс на b_search_content и таблицах инфоблоков

Таблица b_search_content — центральная точка поиска Битрикс. Ключевые колонки: TITLE, BODY. Для каталога индексируем b_iblock_element с колонкой SEARCHABLE_CONTENT, которую Битрикс заполняет автоматически.

ALTER TABLE b_search_content ADD FULLTEXT INDEX ft_search_content (TITLE, BODY) WITH PARSER ngram; ALTER TABLE b_iblock_element ADD FULLTEXT INDEX ft_iblock_element_search (NAME, SEARCHABLE_CONTENT) WITH PARSER ngram; 

WITH PARSER ngram — встроенный в MySQL 5.7+ парсер, разбивающий текст на биграммы/триграммы. Хорошо работает для кириллицы, не требует внешних инструментов.

Мониторинг и обслуживание индексов

Проверка состояния индекса
-- Статистика FULLTEXT-индексов InnoDB SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; -- Принудительная пересборка SET GLOBAL innodb_optimize_fulltext_only = ON; OPTIMIZE TABLE b_search_content; SET GLOBAL innodb_optimize_fulltext_only = OFF; 

Эти запросы помогают отслеживать наполнение индекса и при необходимости перестраивать его.

Разработка кастомного компонента для FULLTEXT

Переопределение поиска в Битрикс

Стандартный bitrix:search.page не использует FULLTEXT — он работает через ORM Битрикс с LIKE. Чтобы подключить FULLTEXT, переопределяем запрос в кастомном компоненте-обёртке или через событие OnBeforeIBlockElementGetList.

Минимальный кастомный поиск через FULLTEXT:

namespace Local\Search; class FulltextSearcher { private \Bitrix\Main\DB\Connection $db; public function __construct() { $this->db = \Bitrix\Main\Application::getConnection(); } public function search(string $query, int $page = 1, int $limit = 20): array { $query = $this->sanitizeQuery($query); $offset = ($page - 1) * $limit; // BOOLEAN MODE с префиксным поиском $boolQuery = '+' . implode('* +', explode(' ', $query)) . '*'; $sql = " SELECT sc.ID, sc.TITLE, sc.URL, sc.MODULE_ID, sc.ITEM_ID, MATCH(sc.TITLE, sc.BODY) AGAINST (? IN BOOLEAN MODE) AS relevance FROM b_search_content sc WHERE MATCH(sc.TITLE, sc.BODY) AGAINST (? IN BOOLEAN MODE) AND sc.SITE_ID = ? AND sc.PUBLIC = 'Y' ORDER BY relevance DESC LIMIT ? OFFSET ? "; $result = $this->db->query($sql, [$boolQuery, $boolQuery, SITE_ID, $limit, $offset]); $rows = []; while ($row = $result->fetch()) { $rows[] = $row; } return $rows; } public function count(string $query): int { $boolQuery = '+' . implode('* +', explode(' ', $query)) . '*'; $result = $this->db->query( "SELECT COUNT(*) AS cnt FROM b_search_content WHERE MATCH(TITLE, BODY) AGAINST (? IN BOOLEAN MODE) AND SITE_ID = ? AND PUBLIC = 'Y'", [$boolQuery, SITE_ID] ); return (int)$result->fetch()['cnt']; } private function sanitizeQuery(string $query): string { $query = preg_replace('/[+\-><()\~*"@]+/', ' ', $query); $query = preg_replace('/\s+/', ' ', trim($query)); return mb_substr($query, 0, 255); } } 

Кастомный компонент поиска

Шаблон компонента использует FulltextSearcher вместо стандартного модуля:

// /local/components/local/search.fulltext/component.php if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die(); $query = trim($_GET['q'] ?? ''); if (mb_strlen($query) < 2) { $this->arResult['ITEMS'] = []; $this->arResult['TOTAL'] = 0; $this->IncludeComponentTemplate(); return; } $searcher = new \Local\Search\FulltextSearcher(); $page = max(1, (int)($_GET['PAGEN_1'] ?? 1)); $this->arResult['ITEMS'] = $searcher->search($query, $page); $this->arResult['TOTAL'] = $searcher->count($query); $this->arResult['QUERY'] = htmlspecialchars($query); $this->arResult['PAGE'] = $page; $this->SetResultCacheKeys([]); // поиск не кешируем $this->IncludeComponentTemplate(); 

Сравнение производительности и парсеров

Сравнительные метрики

Метод Время при 100k записей CPU usage Индексация
LIKE %запрос% 5–15 сек 100% одного ядра Не требует
FULLTEXT (BOOLEAN) 0.1–0.5 сек 10–20% Требуется изначальная
Парсер Минимальная длина слова Поддержка кириллицы Требует конфигурации
Стандартный 3 символа Частичная Нет
ngram (биграммы) 2 символа Полная ngram_token_size

Как внедрить FULLTEXT за 5 шагов

  1. Аудит: замер текущего времени поиска, анализ объёма данных.
  2. Конфигурация MySQL: установка ngram_token_size=2, отключение стоп-слов.
  3. Создание индексов: выполнение ALTER TABLE с FULLTEXT и парсером ngram.
  4. Разработка компонента: создание кастомного FulltextSearcher и шаблона.
  5. Тестирование: нагрузочное тестирование, сравнение «до/после».

Что входит в работу

  • Аудит текущего поискового индекса, замер времени запросов.
  • Настройка конфигурации MySQL: ngram_token_size, отключение стоп-слов.
  • Создание FULLTEXT-индексов на b_search_content и/или таблицах инфоблоков.
  • Разработка кастомного компонента поиска с FULLTEXT-запросами.
  • Пересборка индекса Битрикс-поиска (BXSearch::reindex()).
  • Нагрузочное тестирование с отчётом «до/после».
  • Предоставление документации и скриптов миграции.
  • Бесплатная поддержка в течение месяца.

Наш опыт в Битрикс-разработке — более 10 лет, мы успешно ускорили поиск на 50+ проектах. Получите консультацию — пишите, оценим ваш проект за 1 день.

Согласно документации MySQL 8.0, ngram парсер обеспечивает корректную индексацию кириллицы без внешних зависимостей (MySQL Ngram Full-Text Parser).