@inviziblll

Каким образом можно оптимизировать запрос на выборку большого количества записей?

Подскажите каким образом можно оптимизировать запрос метода GetList на выборку большого количества записей из инфоблока. Есть инфоблок новости спорта (sport_news) у элементов которого есть свойство вид спорта (SPORT_TYPE) - это свойство является привязкой к элементу инфоблока Виды спорта. Например есть новость спорта о футболе у нее SPORT_TYPE - ID записи Футбол в инфоблоке Виды спорта.

function sportType($arItem){
	$dbProperty = CIBlockElement::getProperty(
	    	$arItem['IBLOCK_ID'], 
	    	$arItem['ID'], 
	    	array("sort", "asc"), 
	    	array()
	    );
	while ($arProperty = $dbProperty->GetNext()) {
	    if ($arProperty['VALUE']) {
	        if($arProperty['CODE'] == 'SPORT_TYPE'){
	        	$arItem['SPORT_TYPE'][] =  getElementByID($arProperty['VALUE'], $arProperty['LINK_IBLOCK_ID']);
	        }
	   }
	}
	return $arItem;
}


function sportNews($iblockId, $sportTypeId)
{
	$arSelect = array("*", "PROPERTY_*");
	$arFilter = array("IBLOCK_ID"=>$iblockId, "=PROPERTY_SPORT_TYPE"=>$sportTypeId);
	$arItems = [];
	$res = CIBlockElement::GetList(array(), $arFilter, false, array("nPageSize"=>500), $arSelect);
	while($arItem = $res->fetch()){
		$arItems[] = sportType($arItem); // получаем значение свойства вид спорта (тип Привязка к элементам)
	}
	return$arItems;
}
			
$iblockId = 10; // ID инфоблок новости спорта
$sportTypeId = 5; // ID элемента инфоблока виды спорта (футбол)
sportNews($iblockId, $sportTypeId)

Каким образом можно оптимизировать данный код для работы с большими выборками записей? Может быть убрать вызов функции sportType из цикла while Как в таком случае лучше будет получить значения свойства Вид спорта и где вызывать функцию? Можно ли здесь в коде использовать кеширование?
  • Вопрос задан
  • 57 просмотров
Решения вопроса 1
smilingcheater
@smilingcheater
Вы сейчас сначала выбираете из базы все элементы с их свойствами (CIBlockElement::GetList), затем в цикле для каждого элемента дополнительно загружаете ещё раз все его свойства (CIBlockElement::getProperty), а затем ещё одним запросом в цикле получаете данные о связанном элементе (getElementByID), который будет везде одинаков т.к. вы выбираете с фильтрацией как раз по этому свойству.

Я бы предложил сделать так: сначала загрузить все новости, собрать ID связанных типов спорта, потом подгрузить одним отдельным запросом нужную инфу по типам спорта, и распихать её по новостям. Примерный код будет такой:

function sportNews($iblockId, $sportTypeId) {
    $arSelect = ["*", "PROPERTY_*", "PROPERTY_SPORT_TYPE"]; // Добавить в выборку поле типов спорта. Отдельно с указанием кода - чтобы можно было к нему обращаться по коду, а не по ID
    $arFilter = ["IBLOCK_ID" => $iblockId, "=PROPERTY_SPORT_TYPE" => $sportTypeId];
    $arItems  = [];
    $res      = CIBlockElement::GetList([], $arFilter, false, ["nPageSize" => 500], $arSelect);

    $sportTypes = []; // Массив, в который мы собираем ID связанных типов спорта

    while ($arItem = $res->fetch()) {
        $sportTypes = array_merge($sportTypes, $arItem['PROPERTY_SPORT_TYPE_VALUE']); // Собираем в массив
        $arItems[] = $arItem;
    }


    if (!empty($sportTypes)) {
        $sportTypes = array_unique($sportTypes);
        $arFilterSport = ['ID' => $sportTypes, 'IBLOCK_ID' => 'ИД Инфоблока типов спорта'];
        $resSport      = CIBlockElement::GetList([], $arFilterSport);

        $sportReference = [];
        while ($arItem = $resSport->fetch()) {
            $sportReference[$arItem['ID']] = $arItem; // Раскладываем выбранные типы спорта в ассоциативный массив по ID'шникам
        }

        foreach ($arItems as $ind => $arItem) { // Проходимся по всем новостям
            $arItems[$ind]['SPORT_TYPE'] = [];
            foreach ($arItem['PROPERTY_SPORT_TYPE_VALUE'] as $sportTypeId) {
                $arItems[$ind]['SPORT_TYPE'][] = $sportReference[$sportTypeId]; // Рассовываем в них загруженные типы спорта
            }
        }
    }

    return $arItems;
}

$iblockId = 10; // ID инфоблок новости спорта
$sportTypeId = 5; // ID элемента инфоблока виды спорта (футбол)
sportNews($iblockId, $sportTypeId);
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@arturkunev
Спасибо больше, пользовался вашей подсказкой, чтобы спарсить список всех актуальных зеркал букмекерской конторы Фонбет на этом ресурсе теперь оставлю. А так же настроил автоматическую замену домена, в случае блокировки сайта РКНом.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы