Highload-блоки в Битрикс: чек-лист перед запуском в прод
Highload-блок быстр ровно до тех пор, пока в него не полезли выборкой без select, limit и индекса. Что проверить в схеме, запросах и кеше до выкатки на прод и когда блок вообще не нужен.

Допустим, справочник брендов завели в highload-блоке и вывели через getList() без параметров. На 500 строках всё работает. На 200 000 каждый заход на страницу тащит их все в память PHP, и блок получает ярлык «медленного». Но блок тут ни при чём: это обычная таблица MySQL с ORM1 поверх, и законы таблиц действуют на него полностью. Чек-лист ниже написан для «1С-Битрикс: Управление сайтом» на ядре D7 (main 20.x и новее), MySQL 5.7 и 8.0, PHP 7.4 и 8.x. Имена методов сверяйте с документацией своей версии.
Highload, инфоблок или своя таблица
| Вариант | Что выигрываете | Чем платите |
|---|---|---|
| Инфоблок | Страницы элементов, разделы, ЧПУ, SEO-поля, права на элемент, готовые компоненты | Свойства хранятся отдельно от элемента, поэтому выборки с фильтром по нескольким свойствам дороже |
| Highload-блок | Одна таблица, колонка на поле, быстрый фильтр по проиндексированным полям, ORM | Нет разделов, ЧПУ и SEO. Права в запросах D7 не проверяются. Вывод на сайт пишете сами |
| Своя ORM-таблица | Любые типы, составные ключи, связи, индексы в миграции | Модуль, миграции и админка целиком на вас |
Чек-лист до создания блока
- Имя сущности. Латиница, первая буква заглавная. От него зависит имя класса данных, и по нему блок надёжно искать в коде: ID на dev и prod могут разойтись.
- Типы полей. Числа, флаги и даты заводите соответствующими типами, а не строкой. Строка в MySQL хранится как text (проверьте через SHOW CREATE TABLE), и индекс на ней возможен только с длиной префикса.
- Множественные поля нужны, только если вам правда нужен список значений. Они хранятся отдельно от основной таблицы, и фильтр по ним тяжелее.
- Поля для фильтра и сортировки. Выпишите их до запуска: это кандидаты на индекс.
- Права. Доступ к блоку задаётся в админке, но запросы через класс данных его не проверяют. Если данные видны не всем, проверка на вас.
- Объём. Прикиньте число строк через год и замерьте выборки на таком объёме на копии базы, а не на пустом dev.
Запросы: что проверить в коде
Получаем класс данных
Ищем блок по имени сущности, а не по ID.
<?php
// Битрикс main 20.x+, модуль highloadblock должен быть установлен
use Bitrix\Main\Loader;
use Bitrix\Highloadblock\HighloadBlockTable;
if (!Loader::includeModule('highloadblock')) {
throw new \RuntimeException('Модуль highloadblock не установлен');
}
$hlBlock = HighloadBlockTable::getList([
'filter' => ['=NAME' => 'Brands'],
])->fetch();
if (!$hlBlock) {
throw new \RuntimeException('Блок Brands не найден');
}
$dataClass = HighloadBlockTable::compileEntity($hlBlock)->getDataClass();Выбираем только нужное
Поля UF_* ниже взяты для примера, подставьте свои.
<?php
// Плохо: все строки и все колонки, без кеша
$allRows = $dataClass::getList()->fetchAll();
// Лучше: нужные колонки, точный фильтр, страница, кеш на час
$rows = $dataClass::getList([
'select' => ['ID', 'UF_NAME', 'UF_XML_ID'],
'filter' => ['=UF_ACTIVE' => 1],
'order' => ['UF_SORT' => 'ASC', 'ID' => 'ASC'],
'limit' => 50,
'offset' => 0,
'cache' => ['ttl' => 3600],
])->fetchAll();Индексы
Не рассчитывайте, что Битрикс создаст индекс за вас. Проверьте структуру таблицы и добавьте нужное сами.
-- MySQL 5.7/8.0. Имя таблицы смотрите в карточке блока, здесь b_hlbd_brands для примера
SHOW CREATE TABLE b_hlbd_brands;
-- Строковое поле (text): длина префикса обязательна
ALTER TABLE b_hlbd_brands ADD INDEX ix_brands_xml_id (UF_XML_ID(64));
-- Проверка: в колонке key плана должен появиться ix_brands_xml_id
EXPLAIN SELECT ID FROM b_hlbd_brands WHERE UF_XML_ID = 'sample';Highload-блок не быстрее таблицы, на которой он стоит. Всё, что вы не проиндексировали, он честно прочитает целиком.
На большой боевой таблице ALTER может идти долго. Сначала замерьте время на копии.
Кеш: два способа и их цена
- Параметр
cacheв getList(). Одна строка кода. Кеш работает через управляемый кеш Битрикс, поэтому зависит от его настроек на сайте. Записей будет столько, сколько разных запросов вы выполняете. - Свой кеш вокруг готового результата (
Bitrix\Main\Data\Cache). Вы решаете, что хранить и когда сбрасывать, но сброс пишете сами. Тегированный кеш и инвалидация — отдельная тема.
Что ломается
- getList() без limit. На большой таблице упирается в memory_limit. Выбирайте и выгружайте порциями.
- Глубокий offset. MySQL читает и отбрасывает все пропущенные строки, поэтому страница №4000 медленнее первой. Для обхода всей таблицы сортируйте по ID и фильтруйте
'>ID' => $lastId. - Фильтр без индекса. Полный просмотр таблицы. В EXPLAIN ищите значение ALL в колонке type.
- SQL в обход ORM. События не сработают, кеш ORM не сбросится, читатели увидят старые данные.
- Импорт циклом add(). Каждая строка — отдельный INSERT с обработкой событий. Для больших загрузок проверьте, есть ли в вашей версии main пакетное добавление и как оно работает с UF-полями. Результат add() проверяйте через isSuccess().
- Удаление блока в админке убирает и таблицу с данными. Сначала дамп.
Когда что выбирать
- Элемент должен быть страницей на сайте, с ЧПУ, SEO и разделами: инфоблок.
- Плоский справочник, настройки, журнал событий, данные для фильтров и подсчётов: highload-блок.
- Нужны составные ключи, связи между таблицами или нестандартные типы: собственная таблица.
Порог по числу строк у каждого проекта свой. Определяйте его замером на копии боевой базы.
Что делать дальше
- Включите
slow_query_logв MySQL на dev, поставьте небольшое значениеlong_query_timeи прогоните страницы с блоком. - Снимите EXPLAIN по каждому запросу с фильтром и закройте полные просмотры индексами.
- На проде следите за числом запросов к блоку на страницу (панель производительности в разделе «Настройки → Производительность»), временем выборки на реальном объёме и долей попаданий в кеш.
1 ORM (Object-Relational Mapping) — слой, где таблица описана классом, а запросы строятся вызовами методов вместо ручного SQL. D7 — название ядра Битрикс, в котором эта модель принята. Для highload-блока Битрикс на лету собирает такой класс данных по описанию блока и его полей.
Тендерный специалист 44-ФЗ / 223-ФЗ: Разбор PDF-документации закупки, поиск «заточек» под поставщика, чек-лист заявки.
Спросить за 20 ₽Источники: Документация для разработчиков 1С-Битрикс, MySQL Reference Manual: How MySQL Uses Indexes
Частые вопросы
Сколько строк выдержит highload-блок?
У меня другая версия Битрикс, и метод из примера не найден. Что делать?
Безопасно ли добавлять индекс на боевой таблице?
Можно ли писать в таблицу блока обычным SQL?
Проверяет ли D7 права доступа к highload-блоку при getList()?
Почему фильтр по строковому полю медленный, хотя индекс я создал?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.