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

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

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

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1454
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    1017
  • 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
    759
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    879
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    802
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    1162

При розростанні каталогу товарів у 1С-Бітрікс до 200 тисяч елементів стандартний пошук перестає справлятися — час відгуку сягає понад 10 секунд. На одному з проєктів із каталогом на 500 тисяч товарів пошук через LIKE займав до 18 секунд. Після впровадження FULLTEXT з ngram-парсером час знизився до 0.2 секунди — це в 90 разів швидше. Ми провели аудит, налаштували my.cnf, створили індекси та розробили кастомний компонент. Вартість робіт починається від 500$ (залежить від обсягу). Зв'яжіться з нами для оцінки вашого проєкту.

Стандартний пошук Бітрікс працює через компонент 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+ проєктах. Вартість робіт від 500$ (залежить від складності). Отримайте консультацію — пишіть, оцінимо ваш проєкт за 1 день.

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

Як FULLTEXT порівнюється з LIKE?

FULLTEXT в 50-100 разів швидше за LIKE при 100k записів. Тому для великих каталогів це єдине прийнятне рішення.

Як налаштувати ngram парсер?

Додайте в my.cnf: ngram_token_size=2, innodb_ft_min_token_size=2, innodb_ft_enable_stopword=OFF та перестворіть індекси.