Один из наших сайтов Silverstripe находится на виртуальном хостинге и имеет серьезные проблемы с производительностью. Кажется, что проблемы вызваны тем, что общий SQL-сервер ограничивает количество запросов, которые могут быть сделаны.
Страницы, которые работают медленнее, получают 200+ сотен страниц для размещения на карте Google:
$DirectoryItems = DirectoryItem::get()->where("\"Latitude\" IS NOT NULL AND \"Longitude\" IS NOT NULL ")->sort('Title ASC');
$MapItems = new ArrayList();
foreach ($DirectoryItems as $DirectoryItem) {
$MapItems->push(new ArrayData(array(
"Latitude" => $DirectoryItem->Latitude,
"Longitude" => $DirectoryItem->Longitude,
"MapMarkerURL" => $DirectoryItem->MapMarkerURL,
"Title" => addslashes($DirectoryItem->Title),
"Link" => $DirectoryItem->Link()
)));
}
Каждый из 200+ MapItems генерирует собственный SQL-запрос, который перегружает общий SQL-сервер.
Я начал пытаться получить ту же информацию с помощью одного запроса:
$DirectoryItems = DB::query('SELECT `DirectoryItem`.`Latitude`, `DirectoryItem`.`Longitude`, `DirectoryItem`.`MapMarkerURL`, `SiteTree_Live`.`Title`
FROM `DirectoryItem`, `SiteTree_Live`
WHERE `DirectoryItem`.`ID` = `SiteTree_Live`.`ID`
AND `DirectoryItem`.`Latitude` IS NOT NULL AND `DirectoryItem`.`Longitude` IS NOT NULL
ORDER BY `SiteTree_Live`.`Title`');
$MapItems = new ArrayList();
foreach ($DirectoryItems as $DirectoryItem) {
$MapItems->push(new ArrayData(array(
"Latitude" => $DirectoryItem['Latitude'],
"Longitude" => $DirectoryItem['Longitude'],
"MapMarkerURL" => $DirectoryItem['MapMarkerURL'],
"Title" => addslashes($DirectoryItem['Title']),
"Link" => ??????
)));
}
Но это падает, когда дело доходит до получения ссылки на DirectoryItem.
Я думал о добавлении ссылки как поля БД в DirectoryItem, но это начинает казаться излишне сложным для того, что должно быть простой операцией.
Каков наилучший способ получения информации для 200+ DirectoryItems в одном запросе?
Вы смотрели в кеширование? Если вы показываете одни и те же предметы на карте все время, вам не нужно нажимать на БД при каждом запросе.
Увидеть
Требуется огромная нагрузка на ваш сервер, если вы правильно кешируете.
Если у вас все еще есть проблемы при кэшировании, вы должны подумать о лучшем сервере.
Класс SiteTree имеет статическую функцию, которая используется в CMS для получения ссылки на определенный SiteTreeID. Так что вам просто нужно расширить SQL-запрос, чтобы получить идентификатор, и вы можете получить ссылку на любую страницу с помощью идентификатора, позвонив:
$link = SiteTree::link_shortcode_handler(array('id' => $id), false);
Изменить: wmk предложил другой и, вероятно, более перспективный способ использования:
$page = SiteTree::get()->byID($id);
if ($page instanceof SiteTree) $link = $page->Link();
Непроверенные; ЦСИ: http://api.silverstripe.org/master/class-SiteTree.html