Когда сайт открывается медленно, многие сначала винят хостинг или тяжёлые картинки. Но на динамических сайтах один из самых частых источников тормозов — один-два неудачных запроса к базе данных. Одна страница может отправлять десятки запросов, и если хотя бы один из них выполняется несколько секунд, вся страница ждёт столько же. Лог медленных запросов MySQL создан именно для того, чтобы ловить такие запросы, и он даёт точные данные вместо догадок.
Как работает лог медленных запросов
MySQL измеряет время выполнения каждого запроса. Когда лог медленных запросов включён, любой запрос, выполнявшийся дольше заданного порога, записывается в отдельный файл. Порог задаётся параметром long_query_time в секундах и принимает дробные значения, например полсекунды. Помимо текста запроса в лог попадают время выполнения, время ожидания блокировки, число возвращённых и просмотренных строк.
Два последних показателя особенно полезны. Если запрос вернул пользователю 20 строк, но просмотрел для этого миллион, это явный признак отсутствующего индекса. Такой дисбаланс часто говорит о том, что менять нужно не сам запрос, а структуру таблицы.
Включение лога
На собственном VPS или при административном доступе к базе лог можно включить двумя способами. Первый — командой на работающем сервере: изменения вступают в силу сразу, без перезапуска, но пропадут после следующего перезапуска:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
Для постоянной настройки те же значения прописывают в секцию [mysqld] конфигурационного файла MySQL. Расположение файла зависит от системы: в Debian и Ubuntu он обычно в папке /etc/mysql/, в других системах — /etc/my.cnf. У службы MySQL должны быть права на запись в папку лога:
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
# писать и запросы без индексов (временно, лог быстро растёт):
# log_queries_not_using_indexes = 1
Если поставить long_query_time слишком маленьким, лог быстро разрастётся и может заполнить диск. Для начала хорошее значение — одна секунда, а после исправления самых тяжёлых проблем порог можно опустить до полсекунды и ниже, чтобы увидеть следующий слой.
Как читать запись лога
Каждая запись состоит из строк заголовка и текста запроса. В примере ниже запрос выполнялся больше трёх секунд, вернул 24 строки, но просмотрел для этого больше миллиона:
# Time: 2026-11-04T10:15:32.481920Z
# User@Host: shop_user[shop_user] @ localhost []
# Query_time: 3.214 Lock_time: 0.000120 Rows_sent: 24 Rows_examined: 1184302
SET timestamp=1793787332;
SELECT * FROM products WHERE category_id = 17 ORDER BY created_at DESC LIMIT 24;
Глядя на такую запись, первым делом спрашиваешь: есть ли индекс по столбцам category_id и created_at? Чаще всего ответ — нет, и MySQL каждый раз просматривает таблицу целиком.
Инструменты для анализа большого лога
На посещаемом сайте за день набираются тысячи записей, и читать их вручную невозможно. Утилита mysqldumpslow, которая поставляется вместе с MySQL, группирует похожие запросы, обобщает числа и строки и сортирует их по суммарному времени или числу вызовов. Следующая команда покажет десять самых тяжёлых запросов по суммарному времени:
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
Для более глубокого анализа широко используется pt-query-digest из набора Percona Toolkit. Он показывает долю каждой группы запросов в общем времени в процентах, поэтому сразу видно, какое исправление даст наибольший эффект. Часто выясняется, что один-два запроса создают основную часть нагрузки на базу.
Проверка найденного запроса через EXPLAIN
Найдя проблемный запрос, посмотрите план его выполнения командой EXPLAIN. Если в столбце type стоит ALL, это полный просмотр таблицы, а пустой столбец key означает, что индекс не используется. Using filesort в столбце Extra говорит, что сортировка выполняется отдельно, в памяти или на диске:
EXPLAIN SELECT * FROM products
WHERE category_id = 17
ORDER BY created_at DESC LIMIT 24;
Во многих случаях решение — составной индекс по столбцам фильтрации и сортировки. После его добавления снова проверьте запрос через EXPLAIN и убедитесь, что он больше не появляется в логе.
Что можно сделать на виртуальном хостинге
На виртуальном хостинге обычный пользователь не может менять серверные настройки логов, потому что они влияют на всех клиентов. Здесь помогают инструменты уровня приложения. Для WordPress плагин Query Monitor показывает, сколько времени занял каждый запрос на странице, а в Laravel и других фреймворках есть свои логи запросов и отладочные панели. Если нужен точный анализ конкретной страницы, можно оставить запрос через кабинет sayt.uz или в техподдержку.
Пример: страница каталога мебельного магазина
Сайт мебельного магазина из Намангана example.uz быстро открывал главную страницу, но страницы категорий грузились пять-шесть секунд. Владелец уже собирался менять тариф хостинга, но сначала на сутки включили лог медленных запросов. Отчёт mysqldumpslow показал, что почти вся задержка идёт от одного запроса, похожего на пример выше: таблица товаров искалась по категории и дате без индекса.
После добавления индекса из двух столбцов время запроса упало с трёх секунд до нескольких миллисекунд, а страницы категорий стали открываться быстрее секунды. Менять тариф не пришлось. После этого владелец оставил лог включённым и раз в неделю просматривает список самых тяжёлых запросов — так проблема сразу видна, когда добавляется новый плагин или изменение.