Что ты будешь делать для оптимизации медленного SQL-запроса?

«Что ты будешь делать для оптимизации медленного SQL-запроса?» — вопрос из категории Базы данных, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Мой подход к оптимизации запроса состоит из нескольких шагов:

  1. Анализ с помощью EXPLAIN (или EXPLAIN ANALYZE в PostgreSQL). Смотрю на тип доступа к таблицам (seq scan vs index scan), оцениваю стоимость и количество обрабатываемых строк.
  2. Оптимизация индексов. Ищу поля в условиях WHERE, JOIN и ORDER BY, которые не используют индекс. Создаю составные покрывающие индексы, чтобы запрос получал все данные прямо из индекса.
  3. Рефакторинг запроса. Убираю SELECT *, указываю только нужные столбцы. Упрощаю сложные подзапросы или JOIN, если это возможно. Проверяю на наличие "горячих" подзапросов, которые выполняются много раз.

Конкретный пример из опыта: Был запрос для получения последних заказов активных пользователей. EXPLAIN показал полное сканирование таблицы users.

-- Исходный проблемный запрос
SELECT * FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.status = 'active'
ORDER BY o.created_at DESC
LIMIT 100;

-- Оптимизированная версия
-- 1. Явный выбор полей
SELECT u.id, u.email, o.id, o.total_amount, o.created_at
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.status = 'active'
ORDER BY o.created_at DESC
LIMIT 100;

-- 2. Добавлены индексы
CREATE INDEX idx_users_status ON users(status); -- Для фильтрации
CREATE INDEX idx_orders_user_created ON orders(user_id, created_at DESC); -- Для JOIN и сортировки

После добавления индексов время выполнения запроса сократилось с ~2 секунд до ~50 миллисекунд.