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

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

Ответ

Отладка медленного запроса — это системный процесс. Вот мой подход, основанный на практике с C# и SQL Server:

  1. Сбор данных:

    • Включаю логирование запросов в EF Core для захвата сгенерированного SQL.
      optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information);
    • Использую SQL Server Profiler, Extended Events или запросы к динамическим административным представлениям (DMV), например sys.dm_exec_query_stats, чтобы найти самые затратные запросы.
  2. Анализ плана выполнения: Получаю и анализирую Actual Execution Plan в SSMS (Ctrl+M). Ищу:

    • Table/Index Scans вместо Index Seeks.
    • Key Lookups (RID Lookups) — часто указывают на недостающий покрывающий индекс.
    • Высокую стоимость операций сортировки (Sort), хэширования (Hash Match) или удаленного сбора данных (Remote Query).
    • Предупреждения (жёлтые значки) о неверных оценках количества строк или отсутствующих индексах.
  3. Оптимизация: Действия зависят от анализа:

    • Добавление/изменение индексов: Чаще всего проблема здесь. Создаю недостающие индексы, покрывающие условия WHERE, JOIN и SELECT.
      CREATE INDEX IX_Orders_CustomerId_Status ON Orders(CustomerId, Status) INCLUDE (TotalAmount);
    • Рефакторинг запроса: Переписываю сложный запрос, разбиваю на части, устраняю N+1 проблему в EF Core с помощью Include() и Select().
    • Использование возможностей ORM: Применяю AsNoTracking() для операций только для чтения, AsSplitQuery() для избежания избыточных данных в некоторых сценариях.
    • Кэширование: Для редко меняющихся данных рассматриваю кэширование результатов запроса (например, с помощью IMemoryCache или IDistributedCache).
  4. Тестирование: Замеряю производительность до и после изменений с помощью Stopwatch или сравниваю метрики в плане выполнения (логические чтения, затраченное время).