2034 слова | 6 минут
Что убивает производительность
«Битрикс не подходит для высоконагруженных проектов: слишком тяжёлый, негибкий и тормозной. Инфоблоки? Только мешают. Корзина? Переделывать!» — знакомые слова, не правда ли?
Несмотря на широкое распространение, 1С-Битрикс часто критикуют из-за проблем с производительностью на больших проектах, особенно когда речь идет о высоконагруженных интернет-магазинах. Когда проект становится масштабным, совет обычно один: уходить на чистый фреймворк и собирать архитектуру с нуля.
Да, 1С‑Битрикс имеет собственные ограничения. В реальных условиях большинство интернет‑магазинов работает с каталогами от 1 000 до 50 000 товаров. Битрикс успешно справляется с такими объемами данных. Стабильность и производительность проектов достигаются за счет комплексной настройки: от серверного окружения до логики бизнес-процессов. Результата можно добиться, используя встроенные средства оптимизации: фасетный индекс, композитный режим, кэширование на уровне компонентов и продуманная организация инфоблоков.
Параметры тестирования
Платформа: 1С‑Битрикс: Управление сайтом, версия 25.550.100 (редакция «Бизнес»)
Шаблон: стандартный «Интернет-магазин – Одежда» (два инфоблока: каталог товаров и торговые предложения)
Количество разделов каталога: 12
Тестирование проводилось на сервере со следующими характеристиками:
- Процессор — 6 ядер по 3,8 ГГц
- ОЗУ — 10 Гб
- ПЗУ — SSD, 256 Гб
В тесте были задействованы четыре ключевые страницы:
- Детальная страница товара
- Страница списка товаров с умным фильтром
- Страница примененного умного фильтра
- Страница поиска
Какие метрики оценивали:
- Время генерации страницы
- Суммарное количество запросов на странице
- Время выполнения запросов
Также посмотрим, на какой средний RPS можно рассчитывать при разных конфигурациях каталога при идентичных характеристиках сервера.
Нагрузку генерировал Яндекс.Танк в режиме линейного роста: от 10 до 50 RPS в течение 120 секунд (итого 3 600 запросов). Максимальное число инстансов — 20. Для эмуляции пользовательских сценариев использовались страницы каталогов, фильтрации, детальные карточки и страница оформления заказа.
Параметры каталога
| Номер | Товаров | SKU | Кол-во свойств товаров | Кол-во свойств SKU | Типов цен | Кол-во складов | Фасетный индекс | Тип инфоблоков | Средний RPS |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 10 000 | 10 | 20 | 25 | 10 | 10 | да | 1.0 | 25.94 |
| 2 | 10 000 | 10 | 20 | 25 | 50 | 10 | да | 1.0 | 21.32 |
| 3 | 10 000 | 10 | 20 | 25 | 10 | 50 | да | 1.0 | 22.74 |
| 4 | 10 000 | 10 | 20 | 25 | 100 | 50 | да | 1.0 | 19.25 |
| 5 | 10 000 | 10 | 50 | 50 | 100 | 50 | да | 1.0 | 18.57 |
| 6 | 50 000 | 10 | 20 | 10 | 1 | 10 | нет | 1.0 | 20.22 |
| 7 | 50 000 | 10 | 20 | 10 | 1 | 10 | да | 1.0 | 15.56 |
| 8 | 50 000 | 10 | 20 | 10 | 1 | 10 | да | 2.0 | 22.46 |
| 9 | 100 000 | 10 | 20 | 15 | 1 | 10 | да | 2.0 | 14.22 |
Описание полей:
- Фасетный индекс — был сгенерирован фасетный индекс или нет
- Тип инфоблоков — какой тип инфоблока каталога и SKU тестировался
Порядок тестирования
В рамках тестирования проверяли:
-
Какое влияние на производительность оказывает увеличение типов цен, свойств SKU, количество складов (тесты 1–5).
-
Какое влияние на производительность оказывает использование фасетного индекса (тесты 6 и 7).
-
Какое влияние на производительность оказывает использование инфоблоков 2.0 (тесты 6 и 8).
-
На что можно рассчитывать при похожей конфигурации железа и работе с 1 млн SKU (тест 9 в качестве стресс-теста).
Все тесты проводились при выключенном кэшировании. При включенном кэшировании время генерации всех страниц не превышало 0,2 сек.
Результаты тестов
Для начала — сухие цифры с визуализацией.
Количество запросов, которые делает Битрикс
| Номер параметров | Количество запросов на детальной | Количество запросов на странице списка | Количество запросов с примененным фильтром |
|---|---|---|---|
| 1 | 888 | 853 | 539 |
| 2 | 913 | 846 | 531 |
| 3 | 904 | 849 | 537 |
| 4 | 745 | 912 | 663 |
| 5 | 830 | 992 | 743 |
| 6 | 483 | 849 | 537 |
| 7 | 1083 | 830 | 504 |
| 8 | 1078 | 807 | 486 |
| 9 | 871 | 817 | 496 |
Время генерации страниц
| Номер параметров | Время генерации детальной страницы, сек. | Время генерации страницы списка, сек. | Время генерации страницы с примененным фильтром, сек. |
|---|---|---|---|
| 1 | 0,8219 | 0,836 | 0,5571 |
| 2 | 0,8645 | 1,0674 | 0,5794 |
| 3 | 0,8615 | 1,0318 | 0,5793 |
| 4 | 0,8105 | 1,1191 | 0,789 |
| 5 | 0,8453 | 1,7675 | 1,1792 |
| 6 | 0,6437 | 10,4297 | 10,0334 |
| 7 | 1,0272 | 1,3227 | 1,0759 |
| 8 | 0,9494 | 0,9108 | 0,8256 |
| 9 | 0,8053 | 32,7897 | 38,837 |
Время исполнения запросов
| Номер параметров | Время исполнения запросов на детальной странице, сек. | Время исполнения запросов на странице списка, сек. | Время исполнения запросов на странице с примененным фильтром, сек. |
|---|---|---|---|
| 1 | 0,4244 | 0,5351 | 0,3541 |
| 2 | 0,4472 | 0,5705 | 0,3677 |
| 3 | 0,4487 | 0,6046 | 0,3678 |
| 4 | 0,3403 | 0,6948 | 0,5162 |
| 5 | 0,4424 | 1,1077 | 0,825 |
| 6 | 0,4336 | 10,0592 | 9,8315 |
| 7 | 0,5293 | 0,7671 | 0,6776 |
| 8 | 0,5065 | 0,5812 | 0,6752 |
| 9 | 0,4051 | 32,4376 | 38,6649 |
Интерпретация результатов
Ключевые наблюдения по результатам тестов:
-
Увеличение числа ценовых типов (тест №1 vs №2) приводит к незначительному возрастанию общего числа SQL‑запросов и умеренному росту времени их выполнения на всех проверяемых страницах.
-
Увеличение числа складов (сравнение результатов №2 и №3) не влияет на количество запросов и время их исполнения для всех страниц.
-
Рост количества свойств SKU (сравнение результатов №4 и №5) незначительно повышает количество запросов. При этом значительно увеличивается время их исполнения, но только для страниц списка товаров и страниц с примененным фильтром.
В чем причина роста долгих запросов при увеличении количества свойств SKU? Если посмотреть на запросы, которые
выполняются на странице списка товаров, один из самых долгих делает компонент bitrix:catalog.smart.filter. Это запрос
для построения динамических фильтров (фасетов) на странице каталога.
Фасетный индекс
В 1С‑Битрикс фасетный индекс (Property Index) оптимизирует «умный фильтр» и вызовы CIBlockElement::GetList с фильтрацией
по свойствам. Он хранит для каждого раздела и каждого элемента информацию о доступных значениях свойств и типов цен.
Таблица фасетного индекса содержит следующие поля:
IDразделаIDэлементаFACET_ID— id, которое генерируется на основе того, для чего это значение — свойство или тип цены- Значение — хранимое значение
Использование фасетного индекса при вызове CIBlockElement:GetList включается только, если выполнены все следующие условия:
- Происходит фильтрация свойств
- Используется логический оператор
AND - В фильтре есть
IBLOCK_ID - В фильтре есть фильтрация по разделам
SECTION_ID - В фильтре установлена фильтрация по активности
ACTIVE="Y"
Ускорение — это хорошо. Но почему при добавлении небольшого количества свойств мы видим сильную деградацию в скорости выполнения запросов?
Проблема в размере таблицы фасетного индекса. На момент выполнения теста №4 размер таблицы был ~11 млн записей. При
добавлении свойств размер таблицы увеличился до ~18 млн записей. При использовании фасетного индекса к таблице с
элементами выполняется join таблицы с фасетами. А join такой большой таблицы существенно влияет на производительность.
Вывод: если у вас много разделов, много свойств, много типов цен или много sku, то количество записей в таблице
фасетного индекса будет достаточно большим, чтобы mysql легко выполнял к этой таблице join.
На тестовом стенде при количестве записей больше 10 млн в таблице фасетов начинается деградация времени выполнения запросов. Чтобы рассчитать примерный размер таблицы фасетного индекса, можно воспользоваться следующей формулой:
Кол-во записей в таблице фасетов =
кол-во разделов × (
(кол-во товаров × кол-во свойств товаров) +
(кол-во SKU × (кол-во свойств SKU + кол-во типов цен))
)
Время генерации для 50 000 товаров с 10 SKU составило около 50 минут, для 100 000 товаров с 10 SKU — примерно 1,5 часа.
Большое количество свойств
Проблема большого количества записей, которая была выявлена при тестировании с фасетным индексом, на самом деле распространяется и на некоторые другие таблицы, например:
-
При увеличении типов цен будет расти не только таблица фасетов, но и таблица
b_catalog_price, которая хранит цены к каждому sku. -
При увеличении количества складов будет расти таблица
b_catalog_store_product, которая хранит остатки по складам. -
При увеличении количества свойств у sku будет расти таблица
b_iblock_element_property, в которой хранятся значения свойств для всех инфоблоков (если это не инфоблоки 2.0).
Проблему с b_catalog_price и b_catalog_store_product можно заметить только при работе с корзиной или на странице
оформления заказов. А вот проблема большого количества свойств будет сопровождать на всем конверсионном пути.
Битрикс «из коробки» предлагает решение для хранения большого количества свойств — Инфоблоки 2.0. При переводе инфоблоков в режим 2.0 под каждый инфоблок создается отдельная таблица, и свойства хранятся не как отдельные записи, а как столбцы в новой созданной таблице. Из-за этого количество обрабатываемых строк становится в разы меньше.
В наших тестах (№7 и №8) видно незначительное ускорение за счет перехода на инфоблоки 2.0. При переводе инфоблока sku на Инфоблоки 2.0 мы обнаружили резкое падение производительности: время генерации детальных и списковых страниц возросло с ~4 сек. до более чем 10 сек. Причиной оказалось отсутствие индекса mysql на столбец со свойством, в котором указана привязка sku к родительскому товару.
После создания индекса командой:
CREATE INDEX idx_prop19_elem
ON b_iblock_element_prop_s3 (PROPERTY_19, IBLOCK_ELEMENT_ID);
время генерации страниц значительно уменьшилось (результат теста 8).
Поиск
В 1С‑Битрикс реализован собственный поисковый механизм с морфологическим анализом (стемминг): ключевые слова разбиваются
на основы, которые сохраняются в таблицах b_search_content_stem и b_search_stem. В этом исследовании оценивали
исключительно время выполнения поисковых операций без анализа качества поиска и ранжирования.
При индексации 50 000 товаров наблюдалась следующая динамика:
- Первый запрос (без кэша): 600–1000 SQL‑запросов, время отклика ~8 сек.
- Повторный запрос (без кэша): 300–400 запросов, время отклика 1–2 сек.
- Кэшированная страница: 200–300 запросов, время отклика < 1 сек.
Замедление первого запроса объясняется JOIN‑ами крупных таблиц стемминг‑содержимого. Таблица b_search_content_stem
содержит ~29 млн записей. Последующие обращения выполняются быстрее благодаря кэшированию промежуточных результатов.
Заключение и рекомендации
При анализе полученных результатов важно учитывать, что тестирование проводилось на чистом стенде — без кэширования, доработок и с фиксированными характеристиками железа. Это позволяет объективно сравнить разные подходы, но требует осторожности при интерпретации цифр. В реальных условиях многое будет зависеть от архитектуры проекта и качества реализации.
В ходе тестов мы сопоставили различные конфигурации каталога, чтобы выяснить, как на производительность влияют ключевые параметры: количество типов цен, складов, свойств SKU, использование фасетного индекса и переход на инфоблоки 2.0.
Ключевые выводы
-
Каждый дополнительный тип цены добавляет нагрузку на таблицу
b_catalog_priceи на фасетный индекс, увеличивая время генерации страниц на 5–10 %. -
Рост числа складов до 50 практически не влияет на основные страницы каталога, однако отражается на быстродействии корзины и оформлении заказа.
-
Увеличение количества свойств SKU существенно «раздувает» фасетный индекс и таблицу
b_iblock_element_property, что приводит к почти двукратному росту времени выполнения запросов на страницах списка и фильтрации. -
Фасетный индекс ускоряет фильтрацию при небольшом числе свойств, но при росте таблицы фасета свыше ≈ 10 млн записей деградирует из‑за тяжёлых JOIN‑ов.
-
Инфоблоки 2.0 снижают число обрабатываемых строк в таблицах свойств и фасетов, компенсируя часть накладных расходов фасетного индекса, но требуют корректного mysql‑индексирования новых колонок.
Что можно улучшить без доработки компонентов
-
Аудит фильтрации и свойств. Уточните бизнес‑требования: действительно ли нужны все свойства в фильтре? Это напрямую влияет на объем фасетного индекса.
-
Типы цен. По нашему опыту делать больше 10–20 типов цен нецелесообразно. Правильнее в этом случае перейти на кастомные скидки или другие способы расчета индивидуальных цен.
-
Склады. Минимизируйте их количество уже на этапе проектирования — это поможет избежать сложных и дорогих оптимизаций в будущем.
-
Инфоблоки 2.0. Используйте их при количестве товаров от 50 000 и выше, но не забывайте об обязательной индексации MySQL-колонок связей (например,
PROPERTY_CML2_LINK) после миграции. Также учтите, что в Инфоблоках 2.0 каждое свойство превращается в отдельный столбец таблицы, а у MySQL есть ограничения на их количество. Перевод возможен только в случае, когда свойств менее 50. -
Поиск. Индексируйте в поиске только необходимые свойства и поля, иначе
b_search_contentи таблицы стемминга ( лексемы) превращаются в гигантские тормоза.
А если у вас реально большой каталог?
Представим, что у вас:
- 1 млн товаров
- сотни или тысячи свойств
- десятки типов цен
- много складов
при этом базовая оптимизация уже выполнена: железо обновили, MySQL «подкрутили», лицензия Enterprise куплена, но всё равно всё тормозит.
В этом случае стандартные компоненты Битрикс становятся узким горлышком. Они универсальны, но генерируют много SQL-запросов и плохо масштабируются на очень больших объемах.
Что делали мы в таких ситуациях:
-
Вынос свойств в отдельные таблицы. В одном из проектов каталог содержал тысячи свойств, но реально использовалось лишь несколько сотен. Мы вынесли свойства в отдельные Highload-блоки и перешли на инфоблоки 2.0. Это позволило уменьшить фасетный индекс и повысить производительность фильтрации.
-
Внешние поисковые движки. Перенос фильтрации и поиска в специализированные системы вроде ElasticSearch, OpenSearch или Meilisearch. Да, это требует полной переработки компонентов фильтра, поиска и страницы раздела, но отдача — колоссальная. Вынос тяжелых операций в отдельное приложение разгружает основной сайт и ускоряет отклик в разы.
-
Отдельный кэш для детальных страниц. У Битрикс есть технология тегированного кэша. Она заключается в том, что при обновлении любого элемента инфоблока сбрасывается кэш всех компонентов, которые настроены на данный инфоблок. Из-за этого возникает ситуация, когда вы изменяете один товар в инфоблоке, а кэш детальных страниц сбрасывается у всех остальных товаров. Чтобы решить эту проблему, мы реализовывали кастомный кэш детальных страниц, который сбрасывался только в случае реального обновления элемента.
Битрикс может работать стабильно даже на больших объемах при условии грамотной архитектуры, оптимизации и кастомизации. Стандартных решений будет недостаточно, если проект растет, а требования становятся ближе к enterprise‑уровню.