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

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Послуги, які ми пропонуємо
Показано 1 з 1Усі 1626 послуг
Налаштування повнотекстових індексів MySQL для 1С-Бітрікс
Простий
~1 день
Часті запитання

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

Етапи розробки

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

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

При розростанні каталогу товарів у 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 та перестворіть індекси.

rsync -avz на продакшен у п’ятницю ввечері, рестарт php-fpm — і сайт відповідає 502, бо в .settings.php залишилися локальні налаштування БД. Деплой «по-старому» — лотерея. Оновлення модуля через адмінку ламає кастомний шаблон компонента, правки не зафіксовані в Git — відновлення займає години.

Ми проєктуємо передбачуваний DevOps-цикл для проєктів на Бітрікс: від Docker-середовища до алертів у Telegram. Кожен деплой стає рутиною, а не стресом.

Проблеми, які ми вирішуємо

Бітрікс історично жив у парадигмі «правимо файли по FTP на бойовому сервері». Результат: двоє розробників одночасно правлять init.php, затираючи зміни один одного. Оновлення модуля через адмінку ламає шаблон компонента — файли не зафіксовані в /local/templates/. Про падіння сайту дізнаються від клієнта, staging-середовища немає, перевірки йдуть на проді. Вартість такого підходу — години відновлення та втрата бізнес-логіки.

Чому DevOps критичний для Бітрікс-проєктів?

Проєкти на Бітрікс мають специфіку: важкий торговий каталог, обмін з 1С через CommerceML, безліч агентів та подій. Без CI/CD та моніторингу кожна зміна — ризик. Ручний деплой може спричинити тижневий простій. Після впровадження DevOps середня економія трудовитрат — до 12 годин ручної роботи на місяць, а бюджету підтримки — 15 000–25 000 грн на місяць. Наш 5-річний досвід (понад 50 проєктів на Бітрікс) і ліцензійна чистота рішень — гарантія стабільності.

Інструменти та конфігурація

CI/CD: від коміту до продакшену без рук

Git — переводимо проєкт з FTP на Git (GitLab, GitHub, Bitbucket). Структура гілок: main, staging, develop, feature-гілки. .gitignore під Бітрікс — нетривіальне завдання:

/bitrix/cache/
/bitrix/managed_cache/
/bitrix/stack_cache/
/upload/
/bitrix/php_interface/dbconn.php
/bitrix/.settings.php
/bitrix/license_key.php

Пропустиш managed_cache/ — репозиторій розпухне на гігабайти. Забудеш виключити license_key.php — ключ витече.

CI-пайплайн перевіряє код: PHPStan level 5+ ловить звернення до неіснуючих методів CIBlockElement, PHP_CodeSniffer з Bitrix-стандартом, PHPUnit для бізнес-логіки, composer audit, збірка фронту. CD-пайплайн розгортає без участі людини. Мерж у staging — деплой на staging. Мерж у main — деплой на production (з ручним підтвердженням або без). Zero-downtime через symlink-стратегію: нова версія в окремій папці, current → symlink перемикається за мілісекунди. upload/ живе поза релізними директоріями. При помилці healthcheck після деплою symlink відкочується. Інструменти: GitLab CI/CD, GitHub Actions, Deployer (PHP). Deployer зручний для Бітрікс — є готові рецепти для symlink-деплою та shared-директорій.

Як Docker вирішує проблему «у мене працює»?

Docker-середовище фіксує версії всіх компонентів: nginx, PHP, MySQL, Redis. Docker скорочує час розгортання нового розробника в 10 разів порівняно з ручним налаштуванням. Локальна розробка — docker-compose.yml включає nginx + php-fpm 8.1/8.2 + MySQL 8.0 (або MariaDB 10.6) + Redis + Memcached. Новий розробник: git clone + docker-compose up -d — за 5 хвилин пише код. Паралельна робота над різними версіями PHP — через окремі compose-файли.

Особливості Бітрікс у Docker: /upload/ монтується як named volume (не bind mount — інакше на Windows/Mac проблеми з правами та швидкістю). Cron-завдання (/bitrix/modules/main/tools/cron_events.php) — через окремий контейнер з тим же образом або supervisord. Модуль «Проактивний захист» (security) блокує запити через reverse proxy — потрібен правильний REMOTE_ADDR через set_real_ip_from та realip_module. bitrix/php_interface/dbconn.php та .settings.php задаються через змінні оточення.

Production: мультистейдж-збірка (build-стадія для асетів, production-стадія з легким образом), Docker Registry для тегованих образів, оркестрація через Docker Swarm або Kubernetes для великих проєктів.

Як правильно налаштувати nginx та php-fpm для Бітрікс?

Різниця між «сайт гальмує» та 200 ms TTFB — у конфігурації. nginx: location-блоки під Бітрікс обробляють urlrewrite.php для ЧПУ. /bitrix/admin/ закриває доступ по IP через allow/deny. expires 30d для статики — CSS, JS, зображення кешуються браузером. Brotli (стиснення на 15-20% ефективніше gzip) вмикається brotli on; brotli_comp_level 6;. Rate limiting на /bitrix/tools/ захищає від брутфорсу. HTTP/2 push для критичних ресурсів.

php-fpm: pm = dynamic, розрахунок pm.max_children за формулою (RAM - RAM_інших_сервісів) / avg_memory_per_process. Для Бітрікс avg зазвичай 40-80 MB. OPcache: opcache.memory_consumption=256 (стандартних 128 MB недостатньо — Бітрікс тягне тисячі файлів), opcache.max_accelerated_files=20000, opcache.validate_timestamps=0 у продакшені (скидання через cachetool opcache:reset при деплої). php.ini: memory_limit=256M (для важких операцій імпорту до 512M), max_execution_time=60, upload_max_filesize=100M. Slowlog з request_slowlog_timeout=5s знаходить вузькі місця до скарг користувачів.

Інфраструктура та автоматизація

Моніторинг, логування та резервне копіювання

Як відбувається моніторинг та реагування на інциденти? Prometheus + Grafana: метрики CPU, RAM, диска, мережі, стану сервісів. Алерти: CPU > 80% за 5 хвилин, вільна RAM < 500 MB, диск > 85%, php-fpm queue > 0. Node Exporter, MySQL Exporter, PHP-FPM Exporter збирають дані з кожного компонента. Uptime check кожні 60 секунд — алерт у Telegram за хвилину при падінні сайту. Sentry для PHP-помилок — структуровані помилки з контекстом. Моніторинг агентів Бітрікс (b_agent): завислий агент може тихо ламати обмін з 1С годинами — перевіряємо NEXT_EXEC < NOW() - INTERVAL 1 HOUR. Логування: ELK Stack або Loki + Grafana — nginx access/error, php-fpm slow log, MySQL slow query log, помилки Бітрікс. Ротація через logrotate — без неї через півроку access.log займе 50 ГБ.

Staging-середовище ідентичне production: ті ж версії nginx, PHP, MySQL, модулі, налаштування php.ini. Автоматичне оновлення при мержі у staging-гілку. Періодичний клон БД з production з знеособленням персональних даних — UPDATE b_user SET EMAIL = CONCAT('user', ID, '@test.local'), PHONE = ''. HTTP Basic Auth або IP-фільтрація. Robots.txt з Disallow: /. Sandbox-режим платіжних шлюзів для тестування оплати.

Ansible як інфраструктура як код: ansible-playbook site.yml -l production — через 15 хвилин сервер налаштований ідентично. Ролі: common (users, SSH, NTP), web (nginx + php-fpm), db (MySQL + backup), monitoring (Prometheus + exporters). Ansible забезпечує налаштування сервера за 15 хвилин замість 3 годин вручну.

Компонент Частота Зберігання Метод
БД MySQL Кожні 6 годин 30 днів mysqldump --single-transaction + gzip
Файли (upload/) Щоденно 14 днів rsync інкрементальний
Повний бекап Щотижня 60 днів tar + gpg шифрування
Конфіги серверів При зміні У Git Ansible playbooks

Географічна розподіленість — S3-сумісне сховище + окремий сервер в іншому ЦОД. Тестове відновлення щомісяця — бекап без перевірки лише ілюзія безпеки. Cron з повідомленнями: якщо беказ не пройшов — алерт одразу.

Що входить в роботу

  • Документація DevOps-процесу (схема деплою, політика гілок, опис інфраструктури)
  • Налаштовані CI/CD пайплайни (GitLab CI / GitHub Actions) з робочими тригерами
  • Docker-середовище (docker-compose.yml, Dockerfile, конфіги)
  • Ansible-плейбуки для відтворення серверів
  • Моніторинг (Grafana дашборди, алерти в Telegram/Slack)
  • Захищені доступи з ролевою моделлю
  • Навчання команди: два заняття з роботи з CI/CD, Docker та деплоєм
  • Підтримка на етапі впровадження (два тижні після запуску)

Приклад GitLab CI для Бітрікс (фрагмент):

stages:
  - test
  - build
  - deploy

cache:
  paths:
    - vendor/

unit_tests:
  stage: test
  script:
    - composer install --no-progress
    - php vendor/bin/phpunit

deploy_staging:
  stage: deploy
  script:
    - ansible-playbook deploy.yml -l staging
  only:
    - staging

Як проходить впровадження?

  1. Аудит поточного стану — оцінка інфраструктури, софту, процесів. Займає 2-3 дні.
  2. Проектування архітектури — вибір стеку (Docker/K8s/Ansible), узгодження політик CI/CD, налаштування репозиторію.
  3. Налаштування середовищ — Docker-середовище для локальної розробки, staging-середовище, production-сервери.
  4. Реалізація CI/CD — написання пайплайнів, тестування деплою, інтеграція з моніторингом.
  5. Моніторинг та алертинг — встановлення Prometheus + Grafana, налаштування дашбордів та оповіщень.
  6. Навчання команди — два заняття з роботи з інструментами.

Типові терміни впровадження

Завдання Терміни
Docker-середовище для локальної розробки 2-3 дні
CI/CD пайплайн (GitLab CI / GitHub Actions) 1-2 тижні
Staging-середовище 3-5 днів
Моніторинг + алертинг (Prometheus + Grafana) 1-2 тижні
Централізоване логування (ELK/Loki) 1-2 тижні
Ansible-автоматизація серверів 2-3 тижні
Комплексне DevOps-впровадження 4-8 тижнів

DevOps — не проєкт з фінальною датою, а перехід від «закинув по FTP і молюся» до передбачуваних процесів. Кожен деплой — рутина, кожен інцидент — алерт з контекстом, кожен новий розробник — docker-compose up замість триденного налаштування середовища. Отримайте консультацію — зв'яжіться з нами, і за 2-3 дні підготуємо план впровадження. Замовте DevOps-впровадження під ключ — отримайте стабільність і контроль над інфраструктурою.