ГлавнаяБлог15k+ заказов в месяц на 1С-Битрикс без падения под нагрузкой

15k+ заказов в месяц на 1С-Битрикс без падения под нагрузкой

Рамиль Юналиев
Рамиль Юналиев
E-Commerce Lead
7 июля 2026 г.
4 мин чтения

15k+ заказов в месяц — не рекорд, но уже тот уровень, на котором стандартная конфигурация 1С-Битрикс начинает сыпаться на пиках: распродажи, рассылки, боты индексации, набежавшие одновременно. Две вещи снимают основную нагрузку с PHP и MySQL: правильно настроенный композитный кеш и индексы под реальные запросы каталога. Настройка PHP-FPM, OPcache и Redis под сессии — отдельная тема, здесь не про неё. Дальше — почему именно кеш и индексы, а не что-то экзотическое.

Композитный кеш кеширует не всю нагрузку

Композит делит страницу на две части: статичную "оболочку" — HTML, который на первом запросе к URL сохраняется на диск и дальше отдаётся сразу, — и динамические зоны (корзина, данные пользователя, персональные блоки), которые разработчик помечает отдельно в компонентах. Динамические зоны подгружаются отдельным AJAX-запросом уже после того, как статика показана в браузере.

Это работает не только для анонимных посетителей — композит можно включить и для авторизованных групп пользователей, если правильно настроить список групп в настройках (важно не включить туда группы с доступом к административной панели — частая ошибка конфигурации). Но чем персонализированнее страница, тем больше в ней динамических зон и тем меньше реальный выигрыш от статичного кеша — часть работы всё равно уходит в отдельный запрос при каждом показе.

Второе больное место — момент инвалидации. Сбрасывается кеш не по конкретному URL, а по тегам: у каждой закешированной страницы есть привязанные теги (например, iblock_id_N для инфоблока), и при изменении данных Битрикс сбрасывает все страницы с этим тегом разом. Если тег расставлен грубо — на весь инфоблок целиком — смена цены одного товара сбрасывает кеш всего каталога, а не одной карточки. Файл не пересоздаётся сам по себе — он генерируется заново на первый же запрос к сброшенной странице: этот запрос идёт в PHP и MySQL напрямую, дальше страница снова отдаётся из файла.

Главный выигрыш композита — не в том, что PHP отдаёт готовый HTML быстрее, а в том, что PHP может не запускаться вообще. Готовая страница физически лежит файлом в bitrix/html_pages/, и при настроенном nginx (try_files на этот путь) файл отдаётся веб-сервером напрямую, минуя PHP-FPM целиком. Без этой настройки композит просто ускоряет PHP-путь, а не убирает его.

Что с этим реально делать:

  • проверить, настроена ли у nginx отдача из bitrix/html_pages/ напрямую — без этого композит работает, но не даёт главного эффекта;
  • не считать композит защитой от нагрузки "по умолчанию для всех" — то, для каких групп он реально включён, нужно проверять в настройках, а не предполагать;
  • на страницах с большим количеством персонального контента (личный кабинет) выигрыш от композита ограничен — там динамических зон больше, чем статики;
  • расставлять теги кеша по смыслу (на элемент, не на весь инфоблок) — это доработка компонента/шаблона, не галочка в настройках, но именно она не даёт сбросу одной цены чистить весь каталог разом.

Индексы под каталог — то, что реально экономит время БД

1С-Битрикс хранит товары и их свойства по модели "элемент + значения свойств" (EAV) — гибко для админки, но каждое дополнительное свойство в фильтре превращается в лишний JOIN. На каталоге в несколько тысяч позиций это не заметно. На 100k+ позиций и фильтре по 3-4 свойствам разница между "есть индекс под нужную комбинацию колонок" и "индекса нет" — это разница между запросом на десятки миллисекунд и запросом на секунды под нагрузкой.

Для фильтра по свойствам (умный фильтр в каталоге) в Битриксе есть штатный механизм — фасетный индекс (Контент → Инфоблоки → Фасетные индексы). Он один раз собирает свойства элементов в отдельную плоскую таблицу и дальше фильтрует по ней, а не по цепочке JOIN'ов через EAV-таблицы. Для стандартного фильтра каталога это первое, что нужно включить, а не писать вручную индексы под таблицы свойств — MySQL такой ручной индекс использует как любой другой, но пересборка фасета может таблицу свойств пересоздать и снести его без предупреждения.

Ручные индексы MySQL нужны там, где штатный фасетный индекс не участвует — под конкретный медленный запрос, который не покрывается умным фильтром (нестандартная сортировка, кастомная выборка в компоненте и т.п.). Готового универсального примера тут нет и не должно быть — какой индекс нужен, зависит от конкретного запроса и от того, какие индексы на таблице уже есть. Смотреть по факту: включить perfmon, найти в логе медленных запросов конкретный SQL, прогнать через EXPLAIN и добавлять индекс под то, что реально показал план выполнения — не заранее и не по аналогии с чужим примером.

Практическое правило: индекс должен соответствовать не структуре таблицы, а конкретному запросу, который реально выполняется в фильтре и сортировке каталога.

Итог

Ни композитный кеш, ни индексы сами по себе не "решают" нагрузку целиком — они снимают конкретную её часть: композит — повторный полный рендер статичной части страницы, индексы — полное сканирование таблиц под фильтрами каталога. Остальное (личный контент на странице, момент инвалидации кеша, редкие тяжёлые запросы) остаётся и требует отдельного внимания — про это дальше отдельными постами.