Время выполнения запросов при выполнении из Интернета, но сверхбыстро, когда выполняется из 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 одним из исправлений было удаление исправления в КБ. Каждый браузер обрабатывает данные по-разному, поэтому вы можете ожидать разных результатов в отношении производительности. Надеюсь это поможет..