Приходилось ли заниматься оптимизацией хранимых процедур
Что проверяют
Умеете ли вы оптимизировать по плану выполнения, а не по интуиции, и понимаете ли, почему один и тот же запрос ведёт себя по-разному из приложения и из студии. Для разработчика на C# это ещё и проверка, знаете ли вы, что происходит за границей вызова процедуры.
Как отвечать
Опишите порядок. Сначала измерение: находим тяжёлые процедуры через хранилище запросов, включаем SET STATISTICS IO, TIME ON и смотрим фактический план, сравнивая ожидаемое число строк с настоящим. Расхождение на порядки это сигнал про устаревшую статистику или про неудачно закешированный план.
Дальше перечислите типичные причины и что с ними делают:
- условие, при котором индекс не применяется: функция поверх колонки вроде
WHERE YEAR(dt) = @year, шаблон с ведущей маской, неявное приведение типов из-заnvarcharпротивvarchar; - курсор или цикл там, где хватает одной множественной операции;
- скалярная функция в списке выборки, вызываемая для каждой строки;
- подслушивание параметров, когда план построен под редкое значение и не годится для остальных.
Назовите и приёмы правки: OPTION (RECOMPILE) для процедур с сильно разными параметрами, переписывание коррелированного подзапроса в соединение, точечный индекс с включёнными колонками, SET NOCOUNT ON для часто вызываемых процедур. И обязательно повторный замер на объёме, похожем на боевой.
Где спотыкаются
Правят запрос наугад и объявляют победу без замера до и после. На вопрос, какой оператор плана был самым дорогим, ответить оказывается нечем.
Второе: слепо выполняют подсказки о недостающих индексах. Появляются дубли и почти одинаковые индексы, вставка и обновление замедляются, а исходный запрос быстрее не становится.
Третье: сравнивают время в студии и в приложении, не учитывая разные настройки соединения и прогретый кэш. Отсюда рождается загадка «в студии быстро, из кода медленно», у которой причина в другом плане, а не в самой процедуре.