Дата последнего изменения: 15.11.2023
Мелкие запросы, на первый взгляд, не сильно влияют (в относительной оценке) на работу сайта, если при этом на том же сайте есть какой-нибудь явно тяжелый кусок кода, связанный, например, с фильтрацией товаров, который по определению кешированию не поддается.
Достаточно часто в проектах многие используют вызов CIBlockElement::GetById. Простой, удобный метод, когда надо вытащить какое-то поле для элемента инфоблока. Но этот метод тянет все поля и все свойства элемента. В случае инфоблока с большим количеством свойств и большого числа посетителей на сайте этот простой запрос приводит к снижению производительности. А если таких запросов несколько десятков в различных result_modifier у разных компонентов? Оказывается, что в совокупности, несмотря на кеширование, эти вещи создают пиковые нагрузки в момент обновления кеша.
Если уж надо получить название элемента по ID, то лучше воспользоваться GetList с указанием конкретного вытаскиваемого поля элемента.
Соответственно, разница в скорости выполнения будет сильно зависеть от того, что именно надо вытащить, а потому сравнивать надо не просто два метода, а конкретную бизнес-логику конкретного сайта.
Также GetList позволяет выбрать сразу несколько записей, тогда как GetByID только одну.
Единственное преимущество GetById перед GetList с точки зрения разработчика состоит в том, что GetById можно просто вызвать и все. Прямое использование GetList требует определенной работы с кодом (создание массива параметров).
В большинстве случаев это делается в цикле, например в таком:
// неправильный вариант выборки, на каждый элемент делается дополнительный запрос foreach($arResult['ITEMS'] as $ikey => $ival) { $avtorID = intval($ival['PROPERTIES']['AVTOR']['VALUE']); if($avtorID > 0) { $rs = CIBlockElement::GetByID($avtorID); while($ar = $rs->GetNext()) { $arResulr['ITEMS'][$ikey]['AVTOR_INFO'][] = $ar; } } }
но это не правильно. Такой цикл создает множество запросов, что снижает производительность.
Правильный вариант, это использовать один единственный запрос, в котором получать данные для требуемых элементов:
// правильный вариант, информация по авторам выбирается одним запросом и только нужная $avtorID = array(); foreach($arResult['ITEMS'] as $ikey => $ival) { $aID = intval($ival['PROPERTIES']['AVTOR']['VALUE']); if($aID > 0) { $avtorID[] = $aID; } } $avtorID = array_unique($avtorID); $rs = CIBlockElement::GetList( array('ID' => 'ASC'), array( 'IBLOCK_ID' => XX, 'ID' => $avtorID, 'ACTIVE' => 'Y' ), false, false, array('ID', 'NAME', 'PREVIEW_PICTURE') ); while($ar = $rs->GetNext()) { $arResulr['AVTOR_INFO'][$ar['ID']] = $ar; }
// правильный вариант, // информация по книгам и связанная с ними информация по авторам выбирается одним запросом $rs = CIBlockElement::GetList( array('ID' => 'ASC'), array( 'IBLOCK_ID' => YY, 'ACTIVE' => 'Y' ), false, false, array( 'ID', 'NAME', 'PREVIEW_PICTURE', 'PREVIEW_TEXT', 'PROPERTY_AVTOR.NAME', 'PROPERTY_AVTOR.PREVIEW_PICTURE', ) ); while($ar = $rs->GetNext()) { $arResulr['ITEMS'][] = $ar; }
Пример: Необходимо проверить для списка определенных пользователей, состоят ли они в заданной группе.
Типичный код:
foreach ($arSomeUser as $arUser) { $arGroups = CUser::GetUserGroup($arUser['ID']); if(in_array(5, $arGroups)) { // Делаем что-то } }
В этом случае у нас будет столько запросов, сколько пользователей в списке + один на выборку нужных пользователей из всех возможных (самый первый запрос).
Если в группе содержится мало пользователей, то правильнее будет использовать следующий подход:
$rsUser = $arUser->GetList(($by="ID"), ($order="desc"), array('ACTIVE' => 'Y', 'GROUPS_ID' => 5 ....)) while($arUser = $rsUser->GetNext()) { // Делаем что то }