Как вы проводите диагностику и оптимизацию медленного SQL-запроса?

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

Ответ

Оптимизация выполняется пошагово:

  1. Анализ плана выполнения (EXPLAIN / EXPLAIN ANALYZE). Это первый и главный шаг. Ищу:

    • Полные сканирования таблиц (Sequential Scan) вместо использования индексов.
    • Дорогие операции: Nested Loop, Hash Join, сортировки (Sort).
    • Неточные оценки количества строк (плохая статистика).
  2. Поиск "узких мест" и их устранение:

    • Добавление индексов. Чаще всего для колонок в условиях WHERE, JOIN, ORDER BY. Использую покрывающие индексы (Covering Index), чтобы избежать обращений к таблице.
      -- До
      SELECT name, email FROM users WHERE city = 'Berlin'; -- Медленно, если city не проиндексирован
      -- После добавления индекса
      CREATE INDEX idx_users_city ON users(city) INCLUDE (name, email);
    • Переписывание запроса. Упрощение логики, избавление от избыточных подзапросов, корректное использование JOIN вместо IN.
    • Нормализация/денормализация данных. Иногда добавление вычисляемой колонки или небольшой избыточности ускоряет выборки.
    • Обновление статистики. Команда ANALYZE table_name; (в PostgreSQL) помогает планировщику выбрать оптимальный план.
    • Проверка на проблему N+1. Убеждаюсь, что приложение не делает тысячи простых запросов вместо одного сложного.
  3. Профилирование и мониторинг. Использую инструменты БД (pg_stat_statements в PostgreSQL, Slow Query Log в MySQL) для постоянного выявления медленных запросов.