Время ожидания запроса при выполнении из Интернета, но очень быстрое при выполнении из SSMS.

StackOverflow https://stackoverflow.com/questions/2248112

Вопрос

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

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

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

Это было полезно?

Решение

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

Почему?Параметр ARITHABORT — это один из факторов, на который оптимизатор обращает внимание при определении способа выполнения запроса (точнее, для сопоставления плана).Возможно, план в кэше имеет те же настройки, что и SSMS, поэтому он использует кэшированный план, но с противоположным параметром ваш код C# вызывает перекомпиляцию (или, возможно, вы действительно сталкиваетесь с проблемой). ПЛОХОЙ план в кеше), что во многих случаях, безусловно, может снизить производительность.

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

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

SET ARITHABORT ON; SELECT ...

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

Другие советы

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

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

 DBCC DROPCLEANBUFFERS
 DBCC FREEPROCCACHE

Обновлять

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

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

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

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

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

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

У меня была та же проблема, и она была исправлена ​​путем выполнения процедуры «ПЕРЕКОМПИЛЬ».Вы также можете попробовать использовать анализ параметров.Моя проблема была связана с кешем SQL.

Если вы можете изменить свой код, чтобы исправить прослушивание параметров, оптимизация для неизвестной подсказки — ваш лучший вариант.Если вы не можете изменить свой код, лучшим вариантом является exec sp_recompile «имя процесса», который заставит только этот сохраненный процесс получить новый план выполнения.Удаление и повторное создание процесса будет иметь аналогичный эффект, но может привести к ошибкам, если кто-то попытается выполнить процесс, пока вы его удалили.DBCC FREEPROCCACHE удаляет все ваши кэшированные планы, которые могут разрушить вашу систему, вплоть до множества тайм-аутов в производственной среде с тяжелыми транзакциями.Установка arithabort не является решением проблемы, но является полезным инструментом для определения того, является ли проблема перехватом параметров.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top