|
Часто требуется узнать какие-же SQL-запросы и как долго выполняются у нас на сайте, что за расширения дают нагрузку на базу данных, какие из них нужно удалить, чтоб стать счастливым?
Стандартный Joomla!-debug выдаёт только список выполненных SQL-запросов, а такую жизненно важную для нас информацию не даёт:
- SELECT *, RAND() AS ordering
FROM jos_banner WHERE showBanner = 1 AND (imptotal = 0 OR impmade < imptotal) AND cid = 1 AND catid = 33 ORDER BY sticky DESC, ordering LIMIT 0, 1
- UPDATE jos_banner
SET impmade = impmade + 1 WHERE bid = 7
Сейчас мы исправим эту ситуацию, но к сожалению только с помощью хака и вытянем информацию о: 1. Времени выполнения каждого SQL-запроса. 2. Места, из которого этот SQL-запрос был вызван - тоже очень важная информация, что-бы что за расширение виновато.
Итак, возьмём файл /libraries/joomla/database/database/mysql.php и найдём в нём функцию "function query()" (в Joomla! 1.5.15 это строка 206). В оригинале функция выглядит так:
function query()
{
if (!is_resource($this->_resource)) {
return false;
}
// Take a local copy so that we don't modify the original query and cause issues later
$sql = $this->_sql;
if ($this->_limit > 0 || $this->_offset > 0) {
$sql .= ' LIMIT '.$this->_offset.', '.$this->_limit;
}
if ($this->_debug) {
$this->_ticker++;
$this->_log[] = $sql;
}
$this->_errorNum = 0;
$this->_errorMsg = '';
$this->_cursor = mysql_query( $sql, $this->_resource );
if (!$this->_cursor)
{
$this->_errorNum = mysql_errno( $this->_resource );
$this->_errorMsg = mysql_error( $this->_resource )." SQL=$sql";
if ($this->_debug) {
JError::raiseError(500, 'JDatabaseMySQL::query: '.$this->_errorNum.' - '.$this->_errorMsg );
}
return false;
}
return $this->_cursor;
}
Немного исправим её, сделав заметки времени до и после выполнения SQL-запроса и заодно использовав PHP-функцию "debug_backtrace" для получения информации о точках вызова функций, получаем обновлённую функцию:
function query() { if (!is_resource($this->_resource)) { return false; }
// Take a local copy so that we don't modify the original query and cause issues later $sql = $this->_sql; if ($this->_limit > 0 || $this->_offset > 0) { $sql .= ' LIMIT '.$this->_offset.', '.$this->_limit; }
$this->_errorNum = 0; $this->_errorMsg = ''; if ($this->_debug) { $sql_start = round(microtime(), 6); }; $this->_cursor = mysql_query( $sql, $this->_resource ); if ($this->_debug) { $sql_end = round(microtime(), 6); $this->_ticker++; $backtrace = debug_backtrace(); $bcktrc_add = ''; if (is_array($backtrace)) { for ($i = 1; $i < 3; $i++) { if (isset($backtrace[$i]) and is_array($backtrace[$i])) { if (isset($backtrace[$i]['file']) and isset($backtrace[$i]['line'])) { $bcktrc_add .= str_replace(JPATH_BASE, '', $backtrace[$i]['file']).':'.$backtrace[$i]['line']."\n"; } } } } $this->_log[] = $bcktrc_add.'Execute time:'.round(($sql_end - $sql_start), 6)." sec.\n".$sql; }
if (!$this->_cursor) { $this->_errorNum = mysql_errno( $this->_resource ); $this->_errorMsg = mysql_error( $this->_resource )." SQL=$sql";
if ($this->_debug) { JError::raiseError(500, 'JDatabaseMySQL::query: '.$this->_errorNum.' - '.$this->_errorMsg ); } return false; } return $this->_cursor; }
После данных изменений мы уже получим нужную нам информацию:
- /components/com_banners/models/banner.php:79
/modules/mod_banners/helper.php:39 Execute time:0.000818 sec. SELECT *, RAND() AS ordering FROM jos_banner WHERE showBanner = 1 AND (imptotal = 0 OR impmade < imptotal) AND cid = 1 AND catid = 33 ORDER BY sticky DESC, ordering LIMIT 0, 1
- /modules/mod_banners/helper.php:40
/modules/mod_banners/mod_banners.php:23 Execute time:0.000117 sec. UPDATE jos_banner SET impmade = impmade + 1 WHERE bid = 7
P.S> Если у Вас очень реактивный SQL-сервер или простенький SQL-запрос, то у Вас на некоторые запросы будет выводиться время вместе с экспонентой: Execute time:7.4E-5 sec. это значит что запрос выполнился очень быстро, - не стоит этого пугаться ;)
P.P.S> иногда может потребоваться увеличить глубину вывода точек вызова функций (например Community Builder создаёт свой класс для работы с базой данных, поэтому потребуется заглянуть поглубже), для этого в нашей новой функции в строчке for ($i = 1; $i < 3; $i++) { цифру "3" увеличиваем например до "6" (будет выведено "5" ("6"-1) точек вызова)
|