Время выполнения запросов при выполнении из Интернета, но сверхбыстро, когда выполняется из SSMS

Я пытаюсь отлаживать источник таймаута SQL в поддерживаемом мной веб-приложении. У меня есть исходный код кода С#, поэтому я точно знаю, какой код работает. Я отлаживал приложение прямо до строки, которая выполняет код SQL, который истекает, и я смотрю запрос, запущенный в профилировщике SQL.

Когда этот запрос выполняется из Интернета, он истекает через 30 секунд. Однако, когда я вырезал/вставлял запрос точно так, как он представлен в Profiler, и я помещал его в SSMS и запускал его, он возвращается почти мгновенно. Я проследил проблему с тем, что для ARITHABORT установлено значение OFF в соединении, которое используется в Интернете (то есть, если я отключу ARITHABORT OFF в сеансе SSMS, он длится долгое время, и если я верну его обратно, тогда он будет запущен очень быстро). Однако, прочитав описание ARITHABORT, он, похоже, не применяется... Я делаю простой SELECT, и НИКАКОЙ арифметики не выполняется вообще. Просто один INNER JOIN с условием WHERE:

Почему ARITHABORT OFF вызывает такое поведение в этом контексте? Есть ли способ изменить параметр ARITHABORT для этого соединения из SSMS? Я использую SQL Server 2008.

Ответ 1

Итак, ваш код С# отправляет специальный SQL-запрос SQL Server, используя какой метод? Рассматривали ли вы использование хранимой процедуры? Вероятно, это обеспечит такую ​​же производительность (по крайней мере, в движке), независимо от того, кто ее назвал.

Почему? Параметр ARITHABORT - это то, на что оптимизатор смотрит, когда он определяет, как выполнить ваш запрос (точнее, для согласования плана). Возможно, что план в кеше имеет тот же параметр, что и SSMS, поэтому он использует кешированный план, но с противоположной настройкой ваш код С# заставляет перекомпилировать (или, возможно, вы нажимаете действительно BAD-план в кеше), что может во многих случаях повредить производительность.

Если вы уже вызываете хранимую процедуру (вы не отправляли свой запрос, хотя я думаю, что вы это сделали), вы можете попробовать добавить OPTION (RECOMPILE) к оскорбительному запросу (или запросам) в хранимой процедуре. Это будет означать, что эти заявления всегда будут перекомпилировать, но это может помешать использованию плохого плана, который вы, кажется, бьете. Другой вариант - убедиться, что при компиляции хранимой процедуры пакет выполняется с помощью SET ARITHABORT ON.

Наконец, вы, похоже, спрашиваете, как вы можете изменить настройку ARITHABORT в SSMS. Я думаю, что вы хотели спросить, как вы можете заставить параметр ARITHABORT в вашем коде. Если вы решите продолжить отправку ad hoc SQL из своего приложения С#, то, конечно, вы можете отправить команду как текст, который имеет несколько операторов, разделенных полуколониями, например:

SET ARITHABORT ON; SELECT ...

Для получения дополнительной информации о том, почему эта проблема возникает, см. статью Эрланд Соммарског:

Ответ 2

Этот ответ включает способ решения этой проблемы:

Запустив следующие команды в качестве администратора в базе данных, все запросы выполняются как ожидалось независимо от установки ARITHABORT.

 DBCC DROPCLEANBUFFERS
 DBCC FREEPROCCACHE

Update

Похоже, что большинство людей в конечном итоге сталкиваются с этой проблемой очень редко, и вышеупомянутый метод является достойным одноразовым исправлением. Но если конкретный запрос обнаруживает эту проблему более одного раза, более долгосрочным решением этой проблемы будет использование подсказок запросов, таких как OPTIMIZE FOR и OPTION(Recompile), как описано в эта статья.

Ответ 3

У меня была эта проблема много раз раньше, но если у вас есть хранимая процедура с той же проблемой, что и всплывающее хранилище, то проблема будет решена.

Он вызвал параметр sniffing. Вы должны всегда локализовать параметры в сохраненном proc, чтобы избежать этой проблемы в будущем.

Я понимаю, что это может быть не то, чего хочет оригинальный плакат, но может помочь кому-то с той же проблемой.

Ответ 4

Если вы используете Entity Framework, вы должны знать, что параметры запроса для строковых значений по умолчанию отправляются в базу данных как nvarchar. Если столбец базы данных для сравнения - это типизированный varchar, то в зависимости от вашего сопоставления план выполнения запроса может потребовать шага "IMPLICIT CONVERSION", что вызывает полное сканирование. Я мог бы подтвердить это, посмотрев в мониторинг базы данных в опции дорогих запросов, которая отображает план выполнения.

Наконец, объяснение этого поведения в этой статье: https://www.sqlskills.com/blogs/jonathan/implicit-conversions-that-cause-index-scans/

Ответ 5

У меня была такая же проблема, и она была исправлена ​​с помощью процедуры "WITH RECOMPILE". Вы также можете попробовать использовать параметр sniffing. Моя проблема связана с кешем SQL.

Ответ 6

Если вы можете изменить свой код, чтобы исправить параметр sniffing optimize для неизвестного подсказки, это ваш лучший вариант. Если вы не можете изменить свой код, лучшим вариантом будет exec sp_recompile 'name of proc', который заставит только один сохраненный proc получить новый план выполнения. Удаление и повторное создание proc будет иметь аналогичный эффект, но может привести к ошибкам, если кто-то попытается выполнить proc, пока вы его отбросили. DBCC FREEPROCCACHE отбрасывает все ваши кэшированные планы, которые могут разрушить хаос, вплоть до вашей системы, и в том числе вызывать много тайм-аутов в рабочей среде с тяжелыми транзакциями. Настройка arithabort не является решением проблемы, но является полезным инструментом для обнаружения проблем с параметрами.

Ответ 7

У меня такая же проблема при попытке вызвать SP из SMSS, потребовалось 2 секунды, а из webapp (ASP.NET) потребовалось около 3 минут.

Я пробовал все предлагаемые решения sp_recompile, DBCC FREEPROCCACHE и DBCC DROPCLEANBUFFERS, но ничего не исправила мою проблему, но когда попытался параметр sniffing, он сделал трюк и работал отлично.

Ответ 8

Я испытывал те же симптомы. Вопрос, который не был задан здесь, терпит ли он неудачу в разных браузерах? (Edge, Chrome, Opera...). Я обнаружил, что проблема возникает только с Microsoft Edge. После сканирования поддержки Microsoft одним из исправлений было удаление исправления в КБ. Каждый браузер обрабатывает данные по-разному, поэтому вы можете ожидать разных результатов в отношении производительности. Надеюсь это поможет..