Какие изменения внести в индекс для ускорения запроса без изменения кластерного индекса
Что проверяют
Умеете ли вы читать план выполнения и лечить конкретную проблему, а не «добавить ещё индекс». Кластерный индекс трогать нельзя, значит, работа идёт через некластерные индексы и статистику. Следом обычно просят показать, как вы нашли в плане Key Lookup и чем его убрали.
Как отвечать
Начните с диагностики: фактический план, SET STATISTICS IO ON, Query Store для тяжёлых запросов, DMV sys.dm_db_index_usage_stats и sys.dm_db_missing_index_details. Подсказки о недостающих индексах полезны как сигнал, но применять их вслепую нельзя: они часто дублируют друг друга.
Дальше варианты правки:
- покрывающий индекс: в ключе колонки фильтра, остальные нужные колонки в
INCLUDE. Запрос читается из одного индекса, иKey Lookupпропадает; - порядок ключа: сначала равенство, затем диапазон, затем сортировка. Индекс
(CustomerId, CreatedAt)обслужитWHERE CustomerId = @id ORDER BY CreatedAt, обратный порядок нет; - фильтрованный индекс:
CREATE INDEX ... WHERE Status = 'Pending'для малой горячей части большой таблицы; - пересборка на месте:
WITH (DROP_EXISTING = ON)меняет определение индекса за одну операцию,ONLINE = ONтам, где редакция это поддерживает; - индекс по вычисляемой колонке, если в фильтре выражение, и некластерный columnstore для аналитических агрегатов;
- статистика: иногда виноват устаревший план, и хватает
UPDATE STATISTICS.
В EF Core индекс описывают через HasIndex(...).IncludeProperties(...) и HasFilter(...), чтобы он жил в миграциях.
Где спотыкаются
Добавляют в ключ или INCLUDE колонки кластерного ключа. Они и так лежат в каждом некластерном индексе.
Сваливают в INCLUDE половину таблицы. Получается вторая копия данных, которая дорожает на каждой записи.
Не видят неявного преобразования: строка из C# уходит как nvarchar, колонка объявлена varchar, и вместо seek план делает scan. Индекс тут ни при чём, чинится типом параметра.