SQL-оптимизация: 5 запросов, которые ломают базу
Типовые SQL-запросы, которые тормозят базу: от JOIN без условий до DISTINCT в лоб. Почему они опасны и как их переписать правильно, чтобы база работала быстро и стабильно.
1К открытий4К показов
Оптимизация SQL-запросов — это набор вполне конкретных правил, нарушение которых может положить любую базу. Даже один неудачный JOIN или ORDER BY без индекса способны превратить быструю систему в тормозящую. Мы собрали типовые запросы, которые чаще всего убивают производительность, объяснили, почему они опасны, и показали, как переписать их правильно.
1. Запросы без ограничений
Запрос:
Почему он опасен
Такие запросы тянут абсолютно все данные из таблицы, даже если нужны 2–3 поля. На больших таблицах это превращается в тяжелую нагрузку на сервер: растет объём передаваемых данных, замедляется отклик, падает производительность. Если запрос используют в проде (например, при каждом открытии страницы), он легко может «задушить» базу под пиковыми нагрузками.
Как переписать правильно
или
Важно явно указывать необходимые поля и добавлять LIMIT, если не нужны все строки сразу. Это снижает нагрузку и ускоряет ответ.
2. WHERE без индексов
Запрос:
Почему он опасен
Если по полю status нет индекса, база будет проходить всю таблицу построчно (full table scan), чтобы найти нужные строки. На таблицах с миллионами записей это приводит к заметной деградации производительности, особенно при частых запросах. Если таких фильтров несколько, нагрузка на сервер растет лавинообразно.
Как переписать правильно
Добавить индекс по фильтруемому полю:
Переписать запрос, чтобы он использовал индекс:
Если поле часто используется в фильтрах или джоинах — индексировать его почти всегда оправдано. Это резко ускоряет поиск и снижает нагрузку.
3. GROUP BY и агрегаты по большим таблицам
Запрос:
Почему он опасен
GROUP BY заставляет базу данных сначала обработать все строки, а потом сгруппировать их в памяти или на диске. Если таблица содержит миллионы записей и нет подходящих индексов, такой запрос приводит к сортировке или хэшированию огромных объёмов данных. Итог — долгие выполнения, рост потребления оперативной памяти и, в худшем случае, временные таблицы на диске (disk spill). Дополнительную нагрузку дают агрегаты (COUNT, SUM, AVG и др.) без фильтров — база пересчитывает их для всех строк, даже если вам нужна малая часть.
Как переписать правильно
Ограничить выборку с помощью фильтров до агрегации:
Добавить индекс по ключу группировки:
Если данные статичны — использовать материализованные представления или промежуточные агрегации, чтобы не пересчитывать заново каждый раз.
GROUP BY хорошо работает на подготовленных и отфильтрованных данных. Если он упирается в «сырые» миллионы строк — это сигнал к пересмотру логики запроса.
4. Подзапросы в WHERE (особенно некоррелированные)
Запрос
Почему он опасен
Подзапрос в WHERE нередко превращается в лишний проход по таблице. Если оптимизатор не умеет эффективно преобразовать подзапрос в JOIN, он будет сначала выполнять подзапрос (часто без индексов), а потом сверять результаты с основной таблицей. При больших объёмах это означает десятки тысяч сравнений и скачки производительности. Особенно опасны некоррелированные подзапросы, которые не зависят от внешнего запроса — они могут выполняться повторно или создавать временные таблицы.
Как переписать правильно
Заменить подзапрос на JOIN:
Убедиться, что по ключам соединения и фильтрации (customer_id, country) есть индексы:
Если подзапрос всё же нужен — использовать EXISTS, а не IN, чтобы оптимизатор мог «коротко замыкать» проверку:
Подзапросы — удобный синтаксис, но не всегда эффективный. JOIN и индексы почти всегда работают быстрее, особенно на больших таблицах.
5. ORDER BY без индекса
Запрос
Почему он опасен
Когда вы используете ORDER BY по колонке без индекса, база вынуждена сортировать всю выборку в памяти или на диске. Это означает дополнительную нагрузку на CPU, а при больших объёмах данных — полную деградацию производительности. Часто такие запросы встречаются в продакшене в виде пагинации по миллионам строк. В итоге простой «листинг заказов» превращается в многосекундный или даже минутный ответ.
Как переписать правильно
Добавить индекс по полю сортировки:
Ограничить выборку с помощью LIMIT и пагинации:
Использовать составные индексы, если сортировка идёт вместе с фильтром:
А какие запросы убивают вашу базу? пишите в комментариях!
1К открытий4К показов




