Как я использую Highload-блоки в Bitrix, чтобы не убить инфоблоки
В Bitrix очень легко превратить инфоблоки в свалку: в свойствах лежит всё — от брендов до таблиц соответствий. В какой-то момент фильтры начинают еле ползти, а админка — заикаться. Тут я обычно достаю Highload-блоки.
Расскажу, когда я выношу данные в HL-блоки и как с ними работаю, чтобы не страдать потом.
Когда я вообще думаю о Highload-блоке
Я не бегу за HL-блоками с первого дня. Смотрю на признаки:
- в свойствах инфоблока лежат «тяжёлые» справочники (бренды, города, размеры)
- по этим данным активно фильтруют и сортируют
- в админке с ними неудобно работать
- таблицы b_iblock_* уже раздуты, запросы тяжелеют
Если это «словарь» или большая таблица ссылочных данных — почти всегда выношу в HL-блок.
Как я проектирую HL-блок
Подхожу к нему как к обычной таблице БД:
- заранее думаю про индексы по UF_полям, которые будут в фильтрах
- делаю понятные имена полей: UF_CODE, UF_XML_ID, UF_SORT, UF_NAME
- не запихиваю туда всё подряд; один блок — одна сущность
Пример структуры для справочника брендов:
- UF_NAME — название
- UF_CODE — символьный код
- UF_XML_ID — внешний ID
- UF_SORT — сортировка
- UF_ACTIVE — флаг активности
Работа с HL-блоком в коде Базовый шаблон, который я почти всегда использую:
use BitrixHighloadblock as HL; use BitrixMainEntity;
function getBrandByCode(string $code): ?array { $hlBlock = HLHighloadBlockTable::getById(3)->fetch(); $entity = HLHighloadBlockTable::compileEntity($hlBlock); $dataClass = $entity->getDataClass();
$row = $dataClass::getRow([ 'filter' => ['=UF_CODE' => $code, '=UF_ACTIVE' => 1], ]);
return $row ?: null; }
Для списков:
$list = $dataClass::getList([ 'filter' => ['=UF_ACTIVE' => 1], 'select' => ['ID','UF_NAME','UF_CODE'], 'order' => ['UF_SORT' => 'ASC'], ]);
Главное — всегда указывать select, не тянуть лишнее и не забывать про индексы.
Связ**ка HL-блоков с инфоблоками
Ча**ще всего я делаю так:
- в инфоблоке храню только ключ (ID, CODE или XML_ID бренда)
-
на этапе выборки:
-
вытаскиваю все нужные ключи из элементов
- одной пачкой забираю справочник из HL-блока
- маплю по ключу
Это намного быстрее, чем в каждом элементе дергать HL-блок по одному.
Тип**ичные ошибки, которые я вижу
*** HL-блок используют как помойку «для всего» * нет индексов по UF_полям → на большом объёме всё тормозит сильнее, чем инфоблок * в коде каждый раз заново компилируют сущность, вместо небольшого сервиса/обёртки * смешивают ключи (где-то хранится ID, где-то CODE, где-то XML_ID)
Я стараюсь стандартизировать: для связки беру либо UF_XML_ID, либо UF_CODE, и везде держу одно и то же.
Чек-лист: стоит ли выносить данные в HL-блок * Это справочник или таблица ссылочных данных, а не «живые» сущности * По этим данным активно фильтруют/сортируют * Свойства инфоблока уже раздулись и тормозят * Нужна нормальная таблица с индексами, а не свойства-вложенные массивы * Есть понятная схема ключей для связи с инфоблоками
Итог Highload-блоки — не «магический ускоритель Bitrix», а нормальный способ хранить справочники и тяжёлые словари рядом с инфоблоками. Если относиться к ним как к обычным таблицам БД, продумать ключи и индексы и сделать тонкую обёртку для работы в коде, проект становится и быстрее, и понятнее.