[REVO] Кейс: Профайлы преподавателей, или getResources слишком долгий

Под моим надзором находится сайт онлайн-школы. И есть на этом сайте страничка с профайлами преподавателей. Фактически она представляет собой опубликованный родительский ресурс с неопубликованными ресурсами для каждого из преподавателей. Вся информация о преподавателе расположена в «телевизорах» (TV).
На сайте профайл представляет собой ссылку в виде Фото+Имя и всплывающее окошко с более подробной информацией и формой записи на обучение. Все профайлы подцеплялись при помощи getResources и выводились списком.
К тому же есть пара переключателей, которые генерировали список Ajax-запросом без перезагрузки страницы – это «Язык» и «Носитель языка/Русскоязычный преподаватель».
Собственно, это была предыстория.

Профайлов не так уж много – 20-25, однако скорость генерации списка с помощью getResources заставляла меня плакать навзрыд – 5-12с. И чем больше, я знакомился с его документацией, тем меньше я верил в его нормальную работоспособность.


В интернете я наткнулся на интересную штуковину под названием pdoTools, обещавшую быстрый алгоритм, который позволит подцеплять ресурсы с невероятно огромной скоростью благодаря всего одному запросу к базе данных. «То, что нужно» – подумал я.
Но увы – штуковина эта помогла не сильно (если вообще помогла).

И мне в голову пришла сумасшедшая идея – написать собственный сниппет генерации списка. А сумасшедшая она потому, что с MODx я работаю всего пару месяцев и создание сниппетов для меня темный лес.

Идея сниппета до смешного проста – подцепляем ресурсы, создаем список, выводим. То же, что и getResources, только без всяких излишеств. Так же стоит учесть в алгоритме, что список выводится по выборке двух TV – teacher-language и teacher_type. Поэтому будем передавать в сниппет два параметра – teacher_type и teacher_lang.

Код созданного мною сниппета teacher-list:

//Собираем всех учителей
$result = $modx->newQuery('modResource');
$result->where(array( 'parent' => 5 ));
$result->sortby('publishedon', 'DESC');
$collection = $modx->getCollection('modResource', $result);

//Создаем список
foreach($collection as $teacher) {
	if($teacher_type) {
		$type = !(strpos($teacher->getTVValue('teacher_type'), $teacher_type) === false);
	} else {$type = true;}
	if($teacher_lang) {
		$lang = !(strpos($teacher->getTVValue('teacher-language'), $teacher_lang) === false);
	} else {$lang = true;}
	
	if ($type && $lang) {
		$preview = $teacher->getTVValue('preview');
		if ($preview=='')
			$preview = '<div class="media-wr __style-2 no-video"><p class="no-video__text">Видео в процессе записи</p></div>';
		$output .= $modx->getChunk('tpl.teacher-list', array(
			'teacher-photo' => $teacher->getTVValue('teacher-photo'),
			'longtitle' => $teacher->get('longtitle'),
			'preview' => $preview,
			'lang' => $teacher->getTVValue('lang'),
			'edu' => $teacher->getTVValue('edu'),
			'edu-spec' => $teacher->getTVValue('edu-spec')
		));
	}
}

return $output;


При проверке меня снова ждали боль, тлен и страдание. Скорость генерации абсолютно не изменилась. Что ж, меня так просто не остановить. Последним выходом из этой ситуации я видел только подключение принудительного кеширования. Причем кешировать я решил не каждый профайл, а сразу весь результат выборки. Сказано, сделано:

$result = $modx->newQuery('modResource');
$result->where(array( 'parent' => 5 ));
$result->sortby('publishedon', 'DESC');
$collection = $modx->getCollection('modResource', $result);

$output = '';
if ($modx->cacheManager->get('teacher_'.$teacher_type.'_'.$teacher_lang)) {
	// если в кеше есть выбранный результат выборки – берем список из кеша
    $output = $modx->cacheManager->get('teacher_'.$teacher_type.'_'.$teacher_lang);
} else {
	// если по данному результату кеш пуст,
	// то ничего не поделаешь - генерируем список ...
    foreach($collection as $teacher) {
		...
    }
	// ... и записываем список в кеш :)
    $modx->cacheManager->set('teacher_'.$teacher_type.'_'.$teacher_lang, $output);
}

return $output;


После того, как кеш был сохранен, результаты потрясли меня до глубины души! с 5-12с до менее чем 1с независимо от длины списка при Ajax запросах.

I DID IT!

5 комментариев

avatar
а преподавателя добавил нового и кэш в ручную убиваешь?

вам нужно при обновлении и добавлении убивать кэш через плагин, как пример можно глянуть сдесь modx.im/blog/research/91.html
Я бы не всё гамузом кэшировал, а отдельно и общее.
т.е. тогда, при изменении одной записи, была бы всего одна выборка с БД
Комментарий отредактирован 2015-02-26 11:33:54 пользователем artdevue
avatar
Как я и говорил, в MODx пока не сильно разбираюсь. Ваш подход более серьезен. Пока что преподаватели добавляются раз в пару месяцев, так что не критично. Но разобраться в Вашей статье мне будет полезно и в дальнейшем, когда буду чуть лучше понимать принцип работы таких алгоритмов, возьму Ваш метод на вооружение :-)
avatar
да способов много, и каждый способ имет своё существование :)
avatar
modx.pro/development/3144-a-couple-of-tricks-with-xpdo/ — вот еще полезная статья.
avatar
Ого! :-) сейчас попробую
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.