Как понять, что SQL-запрос не оптимален?

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

Ответ

Неоптимальный запрос можно выявить по нескольким ключевым метрикам и признакам в плане выполнения.

Основные индикаторы проблем:

  1. Высокая нагрузка на ресурсы:

    • Длительное время выполнения (CPU TIME, ELAPSED TIME).
    • Большое количество логических и физических операций чтения (I/O).
  2. Неэффективные операции в плане запроса (Execution Plan):

    • Table/Index Scan вместо Index Seek. Это указывает на отсутствие подходящего индекса или его неиспользование.
    • Key Lookup (RID Lookup) — часто возникает при неполном покрывающем индексе, что приводит к дополнительным операциям поиска.
    • Сostly operators: Сортировка (Sort), хэширование (Hash Match) для больших наборов данных, параллелизм (Parallelism) для простых запросов.
    • Завышенные оценки числа строк (Estimated vs Actual Rows) — признак устаревшей статистики.

Практический анализ в SQL Server:

-- Включим сбор статистики по времени и I/O
SET STATISTICS TIME ON;
SET STATISTICS IO ON;

-- Выполним проблемный запрос
SELECT o.*, c.Name
FROM dbo.Orders o
JOIN dbo.Customers c ON o.CustomerId = c.Id
WHERE o.Status = 'Pending' AND o.CreatedDate > '2023-01-01';

-- После выполнения смотрим вкладку "Messages" для статистики.
-- Анализируем графический план выполнения (включается Ctrl+M или SET SHOWPLAN_XML ON).

Направления для оптимизации:

  • Индексы: Создать недостающие, проверить использование существующих, рассмотреть покрывающие (covering) или columnstore индексы для аналитики.
  • Рефакторинг запроса:
    • Избегать SELECT *, явно перечислять нужные столбцы.
    • Заменять коррелированные подзапросы на JOIN или APPLY.
    • Упрощать условия WHERE и JOIN.
  • Обновление статистики: UPDATE STATISTICS TableName;
  • Параметризация: Убедиться, что запросы параметризованы для эффективного повторного использования кэшированного плана.