Медленные запросы в MySQL и PostgreSQL: как их найти и обезвредить
Обе СУБД умеют показывать, какие запросы выполняются дольше всего: MySQL делает это через slow query log и Performance Schema, PostgreSQL — через расширение pg_stat_statements и настройку log_min_duration_statement. Разница не в том, «может» или «не может» база найти проблему, а в том, насколько подробную картину она даёт и как удобно эту картину читать.
Почему вообще запросы начинают тормозить?
Причин обычно несколько: таблица выросла и старые индексы перестали справляться, кто-то написал запрос без индекса вообще, база не успевает обновлять статистику, или сервер просто упирается в память и диск. Проблема редко приходит одна — чаще это цепочка: сначала растёт таблица, потом старый запрос начинает делать полное сканирование, потом к нему присоединяются ещё десять таких же, и сервер уходит в очередь. Поэтому первый шаг — не гадать, а посмотреть логи и статистику: система сама покажет, кто виноват.
Как найти медленные запросы в MySQL?
Главный инструмент — slow query log. Он включается настройкой slow_query_log и параметром long_query_time, который задаёт порог в секундах: всё, что выполняется дольше, попадает в отдельный файл. Там видно сам текст запроса, время выполнения, число просмотренных строк. Дополнительно можно включить log_queries_not_using_indexes — тогда в лог попадут даже быстрые, но «неправильные» запросы, которые обходятся без индекса просто потому, что таблица пока маленькая.
Для более глубокого анализа есть Performance Schema — встроенный механизм сбора статистики о работе сервера: сколько раз выполнялся запрос, сколько суммарно времени занял, сколько было блокировок. Читать сырые логи неудобно, поэтому на практике их часто прогоняют через утилиту pt-query-digest из набора Percona Toolkit — она группирует похожие запросы и показывает топ самых «тяжёлых» по суммарному времени, а не по единичному случаю.
А как это устроено в PostgreSQL?
В PostgreSQL похожий принцип, но чуть другой инструмент по умолчанию. Параметр log_min_duration_statement задаёт порог в миллисекундах, после которого запрос попадает в лог сервера. А расширение pg_stat_statements, которое можно подключить практически на любой инсталляции, ведёт статистику по всем запросам за время работы сервера: сколько раз выполнялся, сколько времени занял суммарно и в среднем, сколько строк вернул. Это удобнее, чем читать сырые логи построчно — сразу видно рейтинг самых затратных запросов.
Отдельный плюс PostgreSQL — команда EXPLAIN ANALYZE, которая не просто показывает план выполнения запроса, а реально его выполняет и показывает, сколько времени заняла каждая стадия: сканирование таблицы, соединение, сортировка. В MySQL похожий функционал появился в EXPLAIN ANALYZE начиная с восьмой версии, но исторически инструменты анализа планов у PostgreSQL были богаче и подробнее — это одна из причин, почему аналитические нагрузки чаще уходят именно туда.
Что делать, когда виновник найден?
Дальше начинается работа руками, а не логами. Типичный список действий:
- проверить, есть ли индекс на поля, по которым идёт фильтрация или соединение таблиц;
- посмотреть план выполнения — не сканирует ли база всю таблицу целиком там, где достаточно взять несколько строк;
- обновить статистику таблиц (ANALYZE в PostgreSQL, ANALYZE TABLE в MySQL) — планировщик строит планы на основе устаревших данных, если статистика давно не обновлялась;
- переписать сам запрос — иногда одна и та же выборка через JOIN работает быстрее, чем через подзапрос, и наоборот;
- вынести тяжёлую аналитику на отдельную реплику, чтобы она не мешала основной нагрузке.
Важно проверять эффект от каждого изменения по отдельности, а не менять всё сразу — иначе непонятно, что именно помогло, а что оказалось лишним.
Клауд АйСи — цифровые сервисы для бизнеса в одном кабинете: 1С в облаке с ежедневными резервными копиями, конструктор сайтов, Умный онлайн-чат и проверка контрагентов.
Ваши данные под защитой. Есть бесплатные тарифы навсегда.
Можно ли поймать проблему до того, как пользователи начнут жаловаться?
Да, и это разумнее, чем разбирать логи постфактум. Есть смысл настроить регулярный сбор статистики — например, раз в сутки автоматически выгружать топ самых затратных запросов и смотреть, не появился ли новый «лидер». Многие используют для этого связку из slow query log или pg_stat_statements и внешних систем мониторинга, которые строят графики нагрузки и присылают уведомления при отклонениях. Из систем общего назначения для этого часто берут Prometheus с Grafana или готовые агенты мониторинга баз данных — они не заменяют логи СУБД, но помогают увидеть проблему раньше, чем она превратится в массовые жалобы.
Интересный факт: сама идея логировать «медленные» операции для диагностики появилась задолго до баз данных — похожий подход использовали ещё в ранних операционных системах для поиска зависаний диска. Идея проста и универсальна: если что-то занимает подозрительно много времени, это стоит записать и посмотреть отдельно, не дожидаясь, пока накопится критическая масса проблем.
Есть ли различия в том, как база реагирует на нагрузку под капотом?
Да, и это тоже влияет на то, что именно вы увидите в логах. MySQL с движком InnoDB использует буферный пул, который кэширует данные и индексы в памяти, и при нехватке памяти начинает активно вытеснять страницы — это видно как рост операций чтения с диска в логах. PostgreSQL полагается на связку своего shared_buffers и кэша операционной системы, поэтому иногда медленный запрос — это не проблема индекса, а следствие того, что данные просто не помещаются в доступную память и приходится идти на диск. В обоих случаях лог сам подсказывает направление поиска: если время растёт вместе с ростом ввода-вывода, дело в памяти, если время растёт при неизменном объёме данных — скорее всего, дело в индексах или самом запросе.
А если своими силами разбираться некогда?
Ручная диагностика логов требует времени и опыта, и не у каждой компании есть штатный администратор баз данных, который будет регулярно этим заниматься. В сервисе «Клауд АйСи» базы данных разворачиваются уже с настроенным мониторингом и резервным копированием, а специалисты платформы следят за состоянием сервера и помогают разобраться, если запросы вдруг начали выполняться заметно дольше обычного. Это снимает с бизнеса рутинную часть работы — читать логи и подбирать индексы вручную — и оставляет время на развитие самого проекта.
Что в итоге важнее: инструменты диагностики или архитектура запросов?
Инструменты диагностики — это лишь фонарик, который показывает, где темно. Он одинаково хорошо работает и в MySQL, и в PostgreSQL, если его правильно включить и правильно читать результаты. А вот качество самих запросов, продуманность индексов и структура таблиц — это то, что определяет, будет ли фонарик вообще нужен часто. Поэтому регулярный анализ медленных запросов стоит воспринимать не как разовое «тушение пожара», а как обычную гигиену проекта: чем раньше замечена проблема, тем дешевле она обходится.
1С в облаке с резервным копированием
Зарегистрируйтесь и подключите облачную 1С — ежедневные бэкапы и обновления уже включены.
Частые вопросы
Что быстрее найти медленный запрос — в MySQL или PostgreSQL?
Принципиальной разницы нет: обе базы позволяют включить логирование медленных запросов и получить статистику по ним. PostgreSQL за счёт pg_stat_statements и подробного EXPLAIN ANALYZE даёт немного более детальную картину из коробки, но в MySQL похожий результат достигается с помощью Performance Schema и утилит вроде pt-query-digest.
Нужно ли включать slow query log постоянно?
Да, если это не создаёт заметной нагрузки на диск. Постоянное логирование с разумным порогом времени помогает замечать проблему на ранней стадии, а не разбираться постфактум, когда пользователи уже начали жаловаться.
Всегда ли медленный запрос решается добавлением индекса?
Нет. Иногда проблема в устаревшей статистике таблицы, нехватке памяти для кэширования данных или в самой структуре запроса. Индекс — частое, но не единственное решение.