При разрастании каталога товаров в 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 шагов
- Аудит: замер текущего времени поиска, анализ объёма данных.
- Конфигурация MySQL: установка
ngram_token_size=2, отключение стоп-слов.
- Создание индексов: выполнение ALTER TABLE с FULLTEXT и парсером ngram.
- Разработка компонента: создание кастомного
FulltextSearcher и шаблона.
- Тестирование: нагрузочное тестирование, сравнение «до/после».
Что входит в работу
- Аудит текущего поискового индекса, замер времени запросов.
- Настройка конфигурации MySQL:
ngram_token_size, отключение стоп-слов.
- Создание FULLTEXT-индексов на
b_search_content и/или таблицах инфоблоков.
- Разработка кастомного компонента поиска с FULLTEXT-запросами.
- Пересборка индекса Битрикс-поиска (
BXSearch::reindex()).
- Нагрузочное тестирование с отчётом «до/после».
- Предоставление документации и скриптов миграции.
- Бесплатная поддержка в течение месяца.
Наш опыт в Битрикс-разработке — более 10 лет, мы успешно ускорили поиск на 50+ проектах. Получите консультацию — пишите, оценим ваш проект за 1 день.
Согласно документации MySQL 8.0, ngram парсер обеспечивает корректную индексацию кириллицы без внешних зависимостей (MySQL Ngram Full-Text Parser).
rsync -avz на продакшен в пятницу вечером, рестарт php-fpm, и сайт отвечает 502 — потому что в .settings.php остались локальные настройки подключения к БД. Классическая ситуация: деплой «по старинке» превращается в лотерею. Другой пример: обновление модуля через админку ломает кастомный шаблон компонента — правки не зафиксированы в системе контроля версий, и восстановление занимает часы.
Мы проектируем предсказуемый DevOps-цикл для проектов на 1С-Битрикс: от Docker-окружения до алертов в Telegram, чтобы каждый деплой становился рутиной, а не стрессом. Ниже — как именно мы решаем реальные проблемы Битрикс-команд.
Проблемы, которые решаем
Битрикс исторически жил в парадигме «правим файлы по FTP на боевом сервере». Сегодня так работают десятки команд. Результат — двое разработчиков одновременно правят init.php, затирая изменения друг друга. Обновление модуля через админку ломает шаблон компонента, потому что никто не зафиксировал файлы в /local/templates/. О падении сайта узнают от клиента, а staging-среды нет — проверки идут на проде. Стоимость такого подхода — часы восстановления и потеря бизнес-логики. Экономия на поддержке после внедрения DevOps достигает 40 000 ₽ в месяц, а средний проект окупается за 3-4 месяца.
Почему DevOps критичен для Битрикс-проектов?
Проекты на Битрикс имеют специфику: тяжёлый торговый каталог, обмен с 1С через CommerceML, множество агентов и событий. Без CI/CD и мониторинга каждое изменение становится риском. Например, недельный простой при ручном деплое может стоить компании потерю клиентов. Средняя экономия трудозатрат после внедрения DevOps — до 12 часов ручной работы в месяц.
CI/CD: от коммита до продакшена без рук
Git — переводим проект с FTP на Git (GitLab, GitHub, Bitbucket). Структура веток: main (production), 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. Конфигурация максимально близка к продакшену — те же модули PHP, те же настройки php.ini.
Локальная разработка — 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 задаются через переменные окружения, а не через volume с продакшен-конфигами.
Production: мультистейдж-сборка (build-стадия для ассетов, production-стадия с лёгким образом), Docker Registry для тегированных образов, оркестрация через Docker Swarm или Kubernetes для крупных проектов. Подробнее о контейнеризации — Wikipedia: Docker.
Как правильно настроить 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 за минуту при падении сайта. Время отклика ключевых URL: /, /catalog/, /personal/order/make/. 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-среда
Staging идентичен production: те же версии nginx, PHP, MySQL, модули, настройки php.ini. Автоматическое обновление при мерже в staging-ветку. Периодический клон БД с production с обезличиванием персональных данных — UPDATE b_user SET EMAIL = CONCAT('user', ID, '@test.local'), PHONE = '' (требование 152-ФЗ). HTTP Basic Auth или IP-фильтрация. Robots.txt c Disallow: /. Sandbox-режим платёжных шлюзов для тестирования оплаты.
Ansible: инфраструктура как код
Новый сервер? ansible-playbook site.yml -l production — через 15 минут всё настроено идентично текущему. Плейбуки покрывают nginx, php-fpm, MySQL, Redis, certbot, firewall. Роли переиспользуемые: common (users, SSH, NTP), web (nginx + php-fpm), db (MySQL + backup), monitoring (Prometheus + exporters). Идемпотентность — повторный запуск ничего не ломает. Inventory: [production], [staging], [development] для групп серверов. Подробнее — Ansible Documentation.
Резервное копирование
| Компонент |
Частота |
Хранение |
Метод |
| БД MySQL |
Каждые 6 часов |
30 дней |
mysqldump --single-transaction + gzip |
| Файлы (upload/) |
Ежедневно |
14 дней |
rsync инкрементальный |
| Полный бекап |
Еженедельно |
60 дней |
tar + gpg шифрование |
| Конфиги серверов |
При изменении |
В Git |
Ansible playbooks |
Географическая распределённость — S3-совместимое хранилище + отдельный сервер в другом ЦОД. Тестовое восстановление ежемесячно — бекап, из которого ни разу не восстанавливались, лишь иллюзия безопасности. Cron с уведомлениями: если бекап не прошёл — алерт сразу.
Что входит в работу
Наш 5-летний опыт (более 50 проектов на Битрикс) позволяет предоставить полный набор результатов для услуги DevOps для 1С-Битрикс:
- Документация 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
Как проходит внедрение?
Процесс разбит на логические этапы, каждый с измеримым результатом:
-
Аудит текущего состояния — оценка инфраструктуры, софта, процессов. Занимает 2-3 дня.
-
Проектирование архитектуры — выбор стека (Docker/K8s/Ansible), согласование политик CI/CD, настройка репозитория.
-
Настройка окружений — Docker-окружение для локальной разработки, staging-среда, production-серверы.
-
Реализация CI/CD — написание пайплайнов, тестирование деплоя, интеграция с мониторингом.
-
Мониторинг и алертинг — установка Prometheus + Grafana, настройка дашбордов и оповещений.
-
Обучение команды — два занятия по работе с инструментами.
Типичные сроки внедрения
| Задача |
Сроки |
| 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-внедрение под ключ — получите стабильность и контроль над инфраструктурой.