Это то, что я узнал из своего исследования.
.NET отправляет настройки подключения, которые не совпадают с настройками, которые вы получаете при входе в Management Studio. Вот что вы увидите, если понюхаете соединение с Sql Profiler:
-- network protocol: TCP/IP
set quoted_identifier off
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls off
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed
Теперь я вставляю эти настройки выше каждого запроса, который я запускаю при входе на сервер sql, чтобы убедиться, что настройки совпадают.
В этом случае я попробовал каждую настройку индивидуально, после отключения и повторного подключения, и обнаружил, что изменение arithabort с выключенного на включенное уменьшило проблему с 90 до 1 секунды.
Наиболее вероятное объяснение связано с анализом параметров, который используется Sql Server для выбора наиболее эффективного плана запроса. При изменении одного из параметров подключения оптимизатор запросов может выбрать другой план, и в этом случае он явно выбрал плохой.
Но я не совсем в этом убежден. Я попытался сравнить фактические планы запросов после изменения этого параметра, и мне еще предстоит увидеть, как diff показывает какие-либо изменения.
Есть ли что-то еще в настройке arithabort, из-за которой в некоторых случаях запрос может выполняться медленно?
Решение казалось простым: просто поместите set arithabort в верхнюю часть хранимой процедуры. Но это может привести к противоположной проблеме: изменить параметры запроса, и внезапно он будет работать быстрее с «выключено», чем «включено».
В настоящее время я выполняю процедуру с перекомпиляцией, чтобы убедиться, что план обновляется каждый раз. Это нормально для этого конкретного отчета, поскольку для его перекомпиляции может потребоваться секунда, и это не слишком заметно в отчете, для возврата которого требуется 1-10 секунд (это монстр).
Но это не вариант для других запросов, которые выполняются гораздо чаще и должны возвращаться как можно быстрее, всего за несколько миллисекунд.