Время ожидания запроса при выполнении из Интернета, но очень быстрое при выполнении из SSMS - PullRequest
41 голосов
/ 12 февраля 2010

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

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

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

Ответы [ 7 ]

39 голосов
/ 12 февраля 2010

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

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

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

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

SET ARITHABORT ON; SELECT ...

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

12 голосов
/ 06 октября 2011

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

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

 DBCC DROPCLEANBUFFERS
 DBCC FREEPROCCACHE

Обновление

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

4 голосов
/ 17 августа 2012

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

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

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

1 голос
/ 21 июля 2018

Если вы используете Entity Framework, вы должны знать, что параметры запроса для строковых значений по умолчанию отправляются в базу данных как nvarchar. Если столбец базы данных для сравнения - это типизированный varchar, то в зависимости от вашего сопоставления план выполнения запроса может потребовать «НЕВЕРНОЕ ПРЕОБРАЗОВАНИЕ» шаг, который вызывает полное сканирование. Я мог бы подтвердить это, посмотрев в мониторинг базы данных в опции дорогих запросов, которая отображает план выполнения.

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

0 голосов
/ 29 марта 2017

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

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

0 голосов
/ 08 января 2016

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

0 голосов
/ 09 июня 2014

У меня была такая же проблема, и она была устранена путем выполнения процедуры «С РЕКОМЕНДУЕМЫМ». Вы также можете попробовать использовать сниффинг параметров. Моя проблема была связана с кешем SQL.

...