Проблема функционирования каталога на больших объемах
KVT:
Сегодня обнаружилась проблема функционирования каталога Zoo на объемах более 1000 позиций (сейчас в каталоге более 6 тыс. позиций, а будет около 18 тыс.). Если коротко, то на больших объемах он начинает усиленно грузить сервер и возрастает нагрузка на сервер БД. В результате тестирования выяснилось, какой из запросов является виновником.
В классе ItemModelItems есть метод getTotal, который вычисляет количество записей просто выбирая все записи из БД, при чем с JOIN'ами и группировками. А потом смотрит сколько выбрано, вместо того, чтобы правильно построить запрос на вычисление количества записей.
Исправленный вариант этого метода должен выглядеть так:
Код:
/**
* Method to get the total number of items
*
* @access public
* @return integer
*/
function getTotal() {
if (empty($this->_total)) {
$db =& JFactory::getDBO();
$table =& $this->getTable($this->_table);
$where = $this->_buildContentWhere();
// parse catalog/category
if (strpos($this->getState('filter_category_id'), ':')) {
list($catalog_id, $category_id) = explode(':', $this->getState('filter_category_id'), 2);
} else {
list($catalog_id, $category_id) = array(0, 0);
}
$query = 'SELECT count(*) FROM '.$table->getTableName().' AS a'
.(($catalog_id > 0 || $category_id > 0)? ' JOIN '.ZOO_TABLE_CATEGORY_ITEM.' AS ci ON a.id = ci.item_id' : '')
.$where;
$db->setQuery($query);
$this->_total = $db->loadResult();
}
return $this->_total;
}
Сервер передумал загружать мои файлы, сославшись на нехватку места, т.ч. оставляю ссылку для скачивания хака: http://www.cms-service.ru/file-11.html
KVT:
Выяснилось еще одно узкое место: при выборке записей из базы для отображения на фронтальной части сайта каталог выбирает все записи заданного каталога/категории и потом делает вырезку нужного количества из массива результатов. При больших объемах PHP расходует всю доступную память и, как следствие - фатальная ошибка. Кроме того, это приводит к трениям с хостером при использовании виртуального хостинга.
Исправляется следующим образом:
в класс TableItem (файл /administrator/components/com_zoo/tables/item.php) добавляется метод getCountFromCategory
Код:
function getCountFromCategory($catalog_id, $category_id, $published = false, $access_id = false){
$date =& JFactory::getDate();
$now = $this->_db->Quote($date->toMySQL());
$null = $this->_db->Quote($this->_db->getNullDate());
$query = "SELECT count(*)"
." FROM ".$this->getTableName()." AS a"
." LEFT JOIN ".ZOO_TABLE_CATEGORY_ITEM." AS b ON a.id = b.item_id"
." WHERE b.catalog_id = ".(int) $catalog_id
." AND b.category_id ".(is_array($category_id)? " IN (".implode(",", $category_id).")" : " = ".(int) $category_id)
.($published == true ? " AND a.state = 1" : "")
.($access_id !== false ? " AND a.access <= ".(int) $access_id : "")
." AND (a.publish_up = ".$null." OR a.publish_up <= ".$now.")"
." AND (a.publish_down = ".$null." OR a.publish_down >= ".$now.")"
;
$this->_db->setQuery($query);
return $this->_db->loadResult();
}
в классе ZooModelCategory (файл /components/com_zoo/models/category.php) метод getItems должен выглядеть так:
Код:
function getItems() {
if (empty($this->items)) {
// set order
$orders = array('date' => 'a.created ASC', 'rdate' => 'a.created DESC',
'alpha' => 'a.name ASC', 'ralpha' => 'a.name DESC',
'hits' => 'a.hits DESC', 'rhits' => 'a.hits ASC',
'ordering' => 'a.ordering ASC', 'rordering' => 'a.ordering DESC');
$order = isset($orders[$this->item_order])? $orders[$this->item_order] : '';
// get items
$table =& JTable::getInstance('item', 'Table');
$table->setCache($this->cache);
$itemsCount = $table->getCountFromCategory($this->catalog_id, $this->category_id, true, $this->user->get('aid', 0));
// set pagination
$this->pagination = new YPagination('page', $itemsCount, $this->page, $this->items_per_page);
$this->pagination->setShowAll($this->items_per_page == 0);
// slice out items
if ($this->pagination->getShowAll()) {
$this->items = $table->getFromCategory($this->catalog_id, $this->category_id, true, $this->user->get('aid', 0), $order, 0, $itemsCount);
} else {
$this->items = $table->getFromCategory($this->catalog_id, $this->category_id, true, $this->user->get('aid', 0), $order, $this->pagination->limitStart(), $this->items_per_page);
}
}
return $this->items;
}
snowindy:
Как сейчас ведет себя производительность? С Вашими модификациями ушли все проблемы, или все равно медленновато?
KVT:
Проблемы ушли, что не может не радовать :-)
CTPAHHuK:
А можно попросить приаттачить исправленные файлики. (Zoo 1.07)
Навигация