Хранимая процедура выполнения случайно падает; тривиальный ALTER исправляет это. Зачем? - PullRequest
5 голосов
/ 05 декабря 2009

У меня есть несколько хранимых процедур в SQL Server 2005, которые, как я заметил, неожиданно завершат работу, если их вызвать из моего приложения ASP.NET MVC, запущенного в веб-ферме IIS6 из четырех серверов. Обычно ожидаемое время выполнения составляет менее секунды; неожиданное аномальное время выполнения составляет 25-45 секунд. Проблема, кажется, никогда не исправляет себя.

Однако, если Я ИЗМЕНИЮ хранимую процедуру (даже если я ничего не изменяю в процедуре, за исключением, возможно, добавления пробела к сценарию, созданному командой SSMS Modify), время завершения возвращается к ожидаемому времени завершения.

IIS и SQL Server работают в разных блоках, оба работают под управлением Windows Server 2003 R2 Enterprise Edition. SQL Server является стандартной версией. Все машины имеют два процессора Xeon E5450 3GHz и 4 ГБ оперативной памяти. Доступ к SQL Server осуществляется по протоколу TCP / IP через гигабитный Ethernet (не уверен, какой физический носитель).

Проблема присутствует со всех веб-серверов в веб-ферме. Когда я вызываю процедуру из окна запроса в SSMS на моей машине разработки, процедура завершается в обычное время. Это странно, потому что у меня сложилось впечатление, что SSMS использует тот же драйвер SqlClient, что и в .NET. Когда я указываю свой экземпляр разработки веб-приложения на производственную базу данных, я снова получаю аномально длительное время завершения. Если мой тайм-аут SqlCommand слишком короткий, я получаю

System.Data.SqlClient.SqlException: Тайм-аут истек. Период ожидания истекший до завершения операция или сервер не отвечает.

Вопрос: Почему выполнение ALTER над хранимой процедурой, не внося никаких изменений в нее, восстанавливает время завершения, как и ожидалось, менее секунды?

Редактировать: Чтобы уточнить, когда процедура работает медленно для приложения, она одновременно прекрасно работает в SSMS с теми же параметрами. Единственное отличие, которое я могу различить, - это учетные данные для входа (в следующий раз, когда я увижу поведение, я буду проверять из SSMS с теми же кредитами). Конечная цель состоит в том, чтобы заставить проки устойчиво работать с ожидаемой скоростью, не требуя периодического вмешательства.

Разрешение: Я хотел бы обновить этот вопрос на случай, если другие столкнутся с этой проблемой. Следуя приведенным ниже ответам, я смог последовательно воспроизвести это поведение. Чтобы проверить, я использую sp_recompile и передаю его одному из восприимчивых звездочек. Затем я запускаю запрос веб-сайта из моего браузера, который вызывает sproc с нетипичными параметрами. Наконец, я инициирую запрос веб-сайта на страницу, которая вызывает sproc с типичными параметрами, и наблюдаю, что запрос не завершается из-за тайм-аута SQL при вызове sproc.

Чтобы решить эту проблему в SQL Server 2005, я добавил OPTIMIZE FOR подсказки к своему SELECT. У всех звездочков, которые были уязвимы, есть шаблон «все в одном», описанный в этой статье . Эта модель, конечно, не идеальна, но является необходимым компромиссом, учитывая временные рамки проекта.

Ответы [ 3 ]

7 голосов
/ 05 декабря 2009

Параметр сниффинг и повторное использование плана. Время от времени вы получаете плохой план. Выполнение команды ALTER приводит к изменению версии метаданных процедуры, поэтому планы должны перекомпилироваться при следующем выполнении. Решение зависит от множества факторов, у вас может быть плохой SQL, вы можете получить неудачную «оптимизацию», которую мы не можем знать. Определите оператор в процедуре, который медленный, когда медленный. SQL Profiler - ваш друг, трассировка SP: StmtCompleted eevnt с продолжительностью> 5000, например.

5 голосов
/ 05 декабря 2009

План выполнения, вероятно, восстановлен.

Существуют различные способы принудительного восстановления, а также способы избежать перехвата параметров, когда план выполнения определяется на основе параметров, но который может не подходить для всех входных данных. Если бы вы были в 2008 году, я бы рекомендовал использовать опцию OPTIMIZE FOR UNKNOWN.

Либо замаскируйте все свои входные переменные локальными переменными, чтобы избежать перехвата параметров, и рассмотрите возможность вызова WITH RECOMPILE или объявления SP таким образом.

Кроме того, убедитесь, что ваша статистика актуальна. Устаревшая статистика может означать, что план больше не годится.

Комментарии в ответе Ремуса также указывают на ряд факторов, которые могут повлиять на то, какой план выберет сервер.

2 голосов
/ 06 декабря 2009

Когда вы говорите, что запрос работает в SSMS, учтите следующее:

  1. Планы запросов кэшируются на основе точной побайтной структуры строки запроса, включая пробелы
  2. Планы для запросов с параметрами могут отличаться от планов с фиксированными значениями (следствие # 1)

Вы можете попробовать использовать SQL Profiler и скопировать и вставить весь медленный запрос оттуда в SSMS, чтобы проверить, все еще ли он медленный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...