Ответ
Мой подход к оптимизации запроса состоит из нескольких шагов:
- Анализ с помощью
EXPLAIN(илиEXPLAIN ANALYZEв PostgreSQL). Смотрю на тип доступа к таблицам (seq scan vs index scan), оцениваю стоимость и количество обрабатываемых строк. - Оптимизация индексов. Ищу поля в условиях
WHERE,JOINиORDER BY, которые не используют индекс. Создаю составные покрывающие индексы, чтобы запрос получал все данные прямо из индекса. - Рефакторинг запроса. Убираю
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 миллисекунд.