CIBlockElement::GetList — самый частый источник тормозов
на страницах с инфоблоками. Метод гибкий и прощает почти любой набор
параметров, поэтому на нём легко написать код, который работает
на тестовых 50 товарах и падает по таймауту на боевых 50 000.
Разберём, какие параметры выборки решают проблему производительности.
Базовый вызов и его цена
<?php
$result = CIBlockElement::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => 14, 'ACTIVE' => 'Y'],
false,
false,
['ID', 'NAME', 'PREVIEW_TEXT', 'PROPERTY_*']
);
while ($element = $result->GetNext()) {
// ...
}
Каждый параметр в этом вызове по умолчанию тянет за собой больше данных,
чем кажется. GetNext() без явного отключения подгружает
ещё и PROPERTY_*, даже если пятый параметр выборки полей
их не включал, — если не передать второй аргумент GetNext(false, false)
явно в false для отключения этого поведения там, где свойства не нужны.
Отключение подсчёта элементов
Четвёртый параметр (постраничная навигация) по умолчанию считает общее
количество найденных элементов отдельным запросом COUNT(*).
Если постраничная навигация не выводится или общее число неважно —
этот запрос лишний:
<?php
$result = CIBlockElement::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => 14, 'ACTIVE' => 'Y'],
false,
['nTopCount' => 20], // ограничение без подсчёта общего количества
['ID', 'NAME']
);
Нужна помощь с Битрикс?
Явное отключение подгрузки свойств и файлов
<?php
while ($element = $result->GetNext(true, false)) {
// первый true — не подгружать PROPERTY_*, если не указаны явно
// второй false — не подставлять полный URL к файлам превью
}
Если свойства всё же нужны, но не все, а два-три конкретных —
их стоит перечислить явно в пятом параметре
(PROPERTY_COLOR, PROPERTY_SIZE) вместо
маски PROPERTY_*, которая подгружает все привязанные
свойства инфоблока целиком.
Фильтрация по свойствам через отдельный индекс
Фильтр вида ['PROPERTY_COLOR' => 'Красный'] в GetList
требует, чтобы MySQL прошёлся по служебной таблице свойств
инфоблока — на больших каталогах это заметно медленнее фильтра
по обычным полям элемента. Если фильтрация по свойствам —
основной сценарий использования раздела каталога (например, витрина
с фильтром по характеристикам), эффективнее рассмотреть фасетный
индекс умного фильтра, который для этого и предназначен, вместо
прямого обращения к GetList на каждый запрос.
Порядок сортировки и индексы
Сортировка по PROPERTY_* полю не использует обычный
индекс базы данных — она требует join с таблицей значений свойств
и сортировку уже после соединения. Сортировка по штатным полям
(SORT, ACTIVE_FROM, ID)
работает быстрее, потому что эти поля хранятся прямо в таблице
элементов и покрыты стандартными индексами модуля.
Кеширование результата
<?php
use Bitrix\Main\Data\Cache;
$cache = Cache::createInstance();
$cacheId = 'catalog_top_' . $iblockId;
$cacheDir = '/catalog/top/';
if ($cache->initCache(3600, $cacheId, $cacheDir)) {
$items = $cache->getVars();
} elseif ($cache->startDataCache()) {
$items = [];
$result = CIBlockElement::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => $iblockId, 'ACTIVE' => 'Y'],
false,
['nTopCount' => 12],
['ID', 'NAME', 'DETAIL_PAGE_URL']
);
while ($element = $result->GetNext(true, false)) {
$items[] = $element;
}
$cache->endDataCache($items);
}
Для блоков, которые не меняются при каждом запросе (подборки, топ
раздела, related-товары), кеш через Bitrix\Main\Data\Cache
снимает нагрузку с базы полностью — GetList выполняется раз в час
вместо на каждый визит.
Частые ошибки
- Маска PROPERTY_* там, где нужны одно-два свойства. Подгружает все привязанные свойства инфоблока лишним запросом.
- Подсчёт общего количества при отключённой пагинации. Лишний COUNT(*) на каждый вызов без реальной надобности.
- Сортировка по PROPERTY_* на большом каталоге. Требует join и сортировку без использования обычного индекса.
- Отсутствие кеша для статичных блоков. Одна и та же выборка выполняется заново на каждый визит страницы.
Итог
Производительность GetList определяется не самим методом,
а тем, что реально запрошено: отключение подсчёта количества
там, где он не нужен, точный список свойств вместо маски,
сортировка по штатным полям и кеш для стабильных блоков — вместе
эти меры превращают тяжёлый запрос в лёгкий без изменения логики
вывода.
