MySQL — выявление медленных запросов

Статья для новичков. В MySQL есть встроенное средство для отслеживания медленных запросов.

В конфиге нужно просписать

log_slow_queries = /var/log/mysql/mysql-slow.log
long_query_time = 1


log_slow_queries — это путь к файлу, в который будут писаться медленные запросы.
long_query_time — время в секундах. запросы, которые длятся более 1 секунды попадут в лог.

Примеры из жизни

Запрос из движка DLE выполняется 2 секунды. Обратите внимание на регулярное выражение. WTF????

SELECT COUNT(*) as count
FROM dle_users
WHERE email = '19kikazz@gmail.com'
OR LOWER(name) REGEXP '[[:<:]]d[rг]j[eеё][rг][i1l!][cс][kк][aа][yу][[:>:]]'
OR name = 'drjerick';

Или вот выборка 7 записей из Wordpress растягивается на 3 секунды

SELECT SQL_CALC_FOUND_ROWS  wp_posts.*
FROM wp_posts
LEFT JOIN wp_post2cat ON (wp_posts.ID = wp_post2cat.post_id)
LEFT JOIN wp_categories ON (wp_post2cat.category_id = wp_categories.cat_ID)
WHERE 1=1
AND category_id IN (1)
AND (post_type = 'post' AND (post_status = 'publish'))
GROUP BY wp_posts.ID
ORDER BY post_date DESC
LIMIT 0, 7;

Высокая точность

Как отслеживать запросы 0.3 секунды — ведь это тоже долгие запросы.
Вариант 1. Есть специальные патчи для MySQL. Легко нагуглить.
Вариант 2. Написать свой небольшой профайлер.
Например, если работа с базой сосредоточена в одном месте (классе).
Код максимально упрощен. Тут показан сам принцип.

class DB {
    function select($query) {
        $data = mysql_query($query);
        return $data;
    }
}

то в этом классе можно прописать что-то типа.
class DB {
    function select($query) {
        $start_time = microtime(true);
        $data = mysql_query($query);
        $end_time = microtime(true);
        $result = $end_time - $start_time;
        $fp = fopen('/var/log/mysql/mysql-slow.log', 'a+');
        flock($fp, LOCK_EX);
        fwrite($fp, $result.' - '.$query); // пишем в файл время и сам запрос
        flock($fp, LOCK_UN);
        fclose($fp);
        return $data;
    }
}

Таким образом мы получим что-то типа
0.032432 - SELECT * FROM city WHERE id=4
1.127535 - SELECT * FROM user WHERE id=5 AND activity=1
0.487652 - SELECT * FROM post INNER JOIN comments ON post.id = comments.post_id WHERE post_status = 'publish'

#1

Можно заюзать percona, там можно указывать доли секунды для медленных запросов: http://www.percona.com/doc/percona-server/5.1/diagnostics/slow_extended.html?id=percona-server:features:slow_extended_51&redirect=2#long_query_time

Рустам, 14.01.2012 - 23:53
#2

Дякую за хорошу ідею)
Доповню свою функцію по роботі з БД - http://www.sergunik.name/?p=178

Sergunik, 16.01.2012 - 13:00
 
английский язык для начинающих
Ашманов Египет Москва РХТУ Россия США Снежинск Таиланд Тушино Урал Челябинская область Яндекс алкоголь английский язык баги база данных безопасность бизнес блоги взлом видео выставка выходные горные лыжи дайвинг дауншифтинг допинг идиотизм инвентарь интернет книги кэширование мозг море музей ноутбук образование оптимизация отдых отпуск пароль плагин пора сваливать программирование программисты путешествия работа работоспособность радиация реклама самогоноварение собеседование социальные сети спам стартап статистика страны тайм-менеджмент техника учеба фантастика фото фриланс хакер экология электронные деньги юмор Ajax CMS DbSimple DDOS email FireFox Google honda htaccess HTML javascript jQuery life md5 MySQL PHP SEO soft SQL vkontakte Web web 2.0 wordpress