SQL код скопирован в буфер обмена
EN PT FR

Урок 10.3 · Время чтения: ~9 мин

Этот урок познакомит вас с инструментами анализа SQL-запросов и способами их оптимизации. Вы узнаете, как «читает» ваш код база данных, что такое план выполнения и как находить «узкие места» в сложных выборках. Мы разберем практическое использование команды EXPLAIN и научимся интерпретировать ее результаты. К концу урока вы сможете не просто писать запросы, но и профессионально диагностировать причины их медленной работы.

Урок 10.3: Понимание методов оптимизации запросов

В предыдущем уроке мы разобрали базовые правила написания эффективного кода. Но что делать, если запрос все равно работает медленно? Чтобы решить проблему производительности, нужно перестать гадать и начать анализировать. Каждый раз, когда вы отправляете запрос базе данных, специальный компонент СУБД — оптимизатор — строит план его выполнения.

Понимание того, как именно СУБД собирается извлекать данные, является ключом к глубокой оптимизации. В этом уроке мы научимся заглядывать во «внутреннюю кухню» сервера, используя основной инструмент разработчика — план выполнения.

Диаграмма анализа плана выполнения SQL-запроса с использованием EXPLAIN и поиском узких мест


Что такое план выполнения

План выполнения — это подробная инструкция, которую составляет СУБД для выполнения конкретного SQL-запроса. В нем описывается:

  • В каком порядке соединяются таблицы.
  • Какие методы доступа используются (сканирование всей таблицы или поиск по индексу).
  • Какое количество строк СУБД ожидает обработать на каждом этапе.
  • Ориентировочная «стоимость» (cost) выполнения каждой операции.

Использование команды EXPLAIN

Практически во всех реляционных СУБД (MySQL, PostgreSQL, MariaDB) основной командой для анализа плана является EXPLAIN.

Базовый синтаксис

Достаточно добавить слово EXPLAIN в начало вашего запроса:

EXPLAIN
SELECT customer_id, first_name, last_name
FROM customer
WHERE active = 1;

Результат: СУБД вернет таблицу, где каждая строка описывает этап выполнения запроса.


На что обращать внимание при анализе

При чтении вывода EXPLAIN критически важны следующие поля:

1. Тип доступа (type или access_type)

Это поле показывает, как СУБД ищет строки:

  • const / eq_ref: Идеально. Поиск по уникальному ключу (одна строка).
  • ref: Очень хорошо. Поиск по индексу, который может вернуть несколько строк.
  • range: Хорошо. Поиск по диапазону значений в индексе (например, BETWEEN или >).
  • index: Посредственно. Полное сканирование индекса.
  • ALL: Опасно. Полное сканирование таблицы (Full Table Scan). Если таблица большая, это причина тормозов.

2. Используемые индексы (key / possible_keys)

Здесь можно увидеть, какой индекс был выбран оптимизатором. Если в поле key стоит NULL, значит, СУБД не нашла подходящего индекса и сканирует всю таблицу.

3. Количество строк (rows)

Это оценочное количество строк, которое СУБД придется проверить для выполнения запроса. Чем меньше это число, тем быстрее отработает запрос.


Практический пример: Поиск проблемы

Допустим, у нас есть запрос для поиска платежей за конкретный день:

EXPLAIN
SELECT * 
FROM payment 
WHERE payment_date = '2005-05-25 11:30:37';

Если в колонке type вы видите ALL, а в keyNULL, значит, индекс по дате отсутствует или не используется.

Решение: Обычно решением является создание индекса по полю, используемому в WHERE. О самих индексах мы подробно поговорим в следующем уроке, но именно EXPLAIN позволяет увидеть необходимость их создания.


Техники оптимизации «на лету»

  1. Оптимизация подзапросов: Иногда замена вложенных подзапросов на JOIN позволяет оптимизатору построить более эффективный план.
  2. Материализация: Для очень сложных тяжелых расчетов, которые не меняются часто, лучше использовать материализованные представления или временные таблицы.
  3. Упрощение логики: Иногда лишние DISTINCT или ORDER BY в подзапросах блокируют возможности оптимизации.

Ключевые выводы этого урока:

  • План выполнения — это основной документ, по которому СУБД выполняет ваш запрос.
  • Используйте EXPLAIN, чтобы увидеть, как именно база данных ищет данные.
  • Избегайте типа доступа ALL (Full Table Scan) на больших таблицах.
  • Поле rows помогает оценить масштаб работы, которую предстоит выполнить серверу.
  • Если индекс не используется (key равен NULL), это повод проверить SARGable-условия или наличие индекса.

Часто задаваемые вопросы

Зачем запускать EXPLAIN, если запрос и так работает?

EXPLAIN помогает увидеть потенциальные проблемы до того, как объем данных вырастет. Запрос может быть «достаточно быстрым» сегодня, но его план уже может содержать признаки будущих узких мест.

Что хуже всего увидеть в плане выполнения?

На больших таблицах тревожный сигнал — тип доступа ALL, который означает полное сканирование. Это не всегда ошибка, но чаще всего повод проверить индексы, условия фильтрации и форму запроса.

Почему поле rows важно при анализе?

rows показывает, сколько строк СУБД ожидает проверить на этапе плана. Большие значения обычно указывают на избыточную работу и помогают быстро найти участок, который нужно оптимизировать в первую очередь.

Вопросы для собеседования

Что такое план выполнения SQL-запроса?

План выполнения — это стратегия, которую строит оптимизатор СУБД для получения результата запроса. В плане видно порядок операций, методы доступа к данным и оценочную стоимость каждого шага.

Какие поля EXPLAIN вы проверяете в первую очередь и почему?

Сначала смотрю на type/access_type, key/possible_keys и rows. Эти поля быстро показывают, использует ли запрос индексы, как именно читаются данные и где может быть основная нагрузка.

Как понять по EXPLAIN, что нужен индекс?

Если в key часто NULL, а type указывает на полный скан, это сигнал проверить индексирование полей из WHERE и JOIN. После добавления индекса полезно повторить EXPLAIN и сравнить план до и после.

В следующем уроке мы перейдем к самому мощному инструменту ускорения — индексам, и научимся создавать их правильно.

Оглавление курса