Почему SET ARITHABORT ON значительно ускоряет запрос?

75

Запрос представляет собой отдельный выбор, содержащий множество уровней группировки и операций агрегирования. С SET ARITHABORT ON это занимает менее секунды, в противном случае это займет несколько минут. Мы видели такое поведение на SQL Server 2000 и 2008.

Джонатан Аллен
источник

Ответы:

62

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

У меня такая же проблема. Для меня это оказалось нюханием параметров, о котором я сначала не понимал достаточно, чтобы о нем заботиться. Я добавил 'set arithabort on', который исправил проблему, но потом вернулся. Тогда я читаю:

http://www.sommarskog.se/query-plan-mysteries.html

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


источник
3
Более шести лет спустя ссылка, приведенная в этом ответе, все еще "требует чтения" ... и все еще актуальна, последняя редакция - декабрь 17 года.
Такрл
30

Приложения .NET подключаются с отключенной по умолчанию опцией, но по умолчанию она включена в Management Studio. В результате сервер фактически кэширует 2 отдельных плана выполнения для большинства / всех процедур. Это влияет на то, как сервер выполняет численные расчеты, и поэтому вы можете получить совершенно разные результаты в зависимости от процедуры. Это на самом деле только один из двух распространенных способов, которыми процесс может получить ужасный план выполнения, другой - перехват параметров.

Посмотрите на https://web.archive.org/web/20150315031719/http://sqladvice.com/blogs/gstark/archive/2008/02/12/Arithabort-Option-Effects-Stored-Procedure-Performance. ASPX для немного больше обсуждения по этому вопросу.

Бен Хоффман
источник
Я согласен с половиной этого ответа. Я очень скептически отношусь к заявлению о численном расчете!
Мартин Смит
2
@Martin: я думаю, что я был неясен. Я просто говорил, что ARITHABORT ON заставляет SQL Server выдавать ошибку при любой ошибке div / 0 или арифметическом переполнении. Когда он выключен, он продолжает работать и по любой причине может вызвать всевозможные ужасные проблемы.
@Ben - Да, извините, я не хотел особо критиковать ваш ответ. Я просто указывал, что было бы очень легко изменить SETопцию, получить лучший план и ошибочно диагностировать это как сам вариант, который виноват. Я не уверен, что парень из твоей ссылки этого не сделал.
Мартин Смит
@Martin - Не проблема, я не думал, что вы нападаете на меня. Другое обсуждение, которое я связал, могло быть немного неясным. Я просто пытался дать подтверждающие доказательства.
@Martin Оглядываясь назад, я считаю, что вы правы.
21

Я бы сказал, что это почти наверняка сниффинг параметров.

Часто утверждается, что это SET OPTIONSможет повлиять на производительность таким образом, но я еще не видел ни одного официального источника для этого утверждения, за исключением случая, когда вы используете индексированные представления / постоянные вычисляемые столбцы.

В этом случае (для SQL2005 + и если ваша база данных не находится в режиме совместимости с SQL2000 ). Если у вас есть ARITHABORTи ANSI_WARNINGS OFFто, и другое, вы обнаружите, что индекс не используется, поэтому может иметь место сканирование, а не желаемый поиск (и некоторые накладные расходы, поскольку постоянный результат вычисления не может быть использован). ADO.NET, кажется, по умолчанию имеет ANSI_WARNINGS ONбыстрый тест, который я только что сделал.

Утверждение в ответе Бена о том, что «способ, которым сервер выполняет численные вычисления», может прибавить минуты к результату, который в противном случае занял бы менее секунды, просто не кажется мне заслуживающим доверия. Я думаю, что, как правило, происходит то, что при исследовании проблемы производительности производительности Profiler используется для идентификации ошибочного запроса. Он вставляется в управляющую студию и запускается и мгновенно возвращает результаты. Единственная очевидная разница между соединениями - это ARITH_ABORTопция.

Быстрый тест в окне Management Studio показывает, что при SET ARITHABORT OFFвключении и выполнении запроса возникает проблема с производительностью, которая, по-видимому, закрыта. Действительно, похоже, что это методология устранения неполадок, используемая в ссылке Грегга Старка .

Однако это игнорирует тот факт, что с этим параметром вы можете получить точно такой же плохой план из кэша .

Такое повторное использование плана может произойти даже в том случае, если вы вошли в систему как другой пользователь, нежели использует подключение к приложению.

Я проверил это, выполнив сначала тестовый запрос из веб-приложения, а затем из Management Studio с, SET ARITHABORT OFFи увидел, что количество пользователей возрастает из приведенного ниже запроса.

SELECT usecounts, cacheobjtype, objtype, text ,query_plan
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) 
CROSS APPLY sys.dm_exec_query_plan(plan_handle) 

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

Более полный список ключей кэша плана здесь

Мартин Смит
источник
13

Я знаю, что опаздываю на эту вечеринку, но для будущих посетителей Мартин абсолютно прав. Мы столкнулись с этой же проблемой - SP работал очень медленно для клиентов .NET, в то время как он быстро работал для SSMS. Изучая и решая проблему, мы проводили систематическое тестирование, о котором спрашивает Кенни Эвитт в своем комментарии к вопросу Мартина.

Используя вариант запроса Мартина, я искал SP в кеше процедур и нашел два из них. Глядя на планы, на самом деле это был случай, когда у одного был включен ARITHABORT, а у другого был ARITHABORT OFF. Версия ARITHABORT OFF имела поиск индекса, в то время как версия ARITHABORT ON использовала сканирование индекса для того же вывода. Учитывая задействованные параметры, поиск по индексу потребовал бы поиска десятков миллионов записей для вывода.

Я удалил две процедуры из кеша, и клиент .NET снова запустил SP, используя те же параметры (которые имели широкий диапазон дат для клиента с большой активностью). ИП вернулся мгновенно. В кэшированном плане использовалось то же сканирование индекса, которое ранее было включено в план ARITHABORT ON, но на этот раз план был для ARITHABORT OFF. Мы запустили SP с теми же параметрами в SSMS и снова получили результаты мгновенно. Теперь мы увидели, что второй план для ARITHABORT ON был кэширован при сканировании индекса.

Затем мы очистили кеш, запустили SP в SSMS с узким диапазоном дат и получили мгновенный результат. Мы обнаружили, что в результирующем кэшированном плане был поиск по индексу, поскольку тот же вывод ранее обрабатывался сканированием (которое также было поиском в исходном плане с выключенным ARITHABORT). Снова из SSMS мы запустили SP, на этот раз с тем же широким диапазоном дат, и увидели ту же ужасную производительность, что и в исходном запросе .NET.

Короче говоря, несоответствие не имело никакого отношения к действительному значению ARITHABORT - при его включении или выключении с любого клиента мы могли получить приемлемую или ужасную производительность: все, что имело значение, это значения параметров, используемые при компиляции и кэшировании плана.

Хотя MSDN указывает, что сама ARITHABORT OFF может оказать негативное влияние на оптимизацию запросов, наше тестирование подтверждает, что Мартин прав: причина была в перехвате параметров, а полученный план не был оптимальным для всех диапазонов параметров.

mdoyle
источник
1
Интересно, что Setting ARITHABORT to OFF can negatively impact query optimization leading to performance issues.означает эта фраза . Говорят ли они просто о невозможности использования индексов для вычисляемых столбцов и представлений (если ANSI_WARNINGSон также отключен), или это действительно имеет какой-то другой эффект.
Мартин Смит
Я не уверен. Интересно, это просто тот случай, когда кто-то из MSDN столкнулся с подобной ситуацией, установил ARTIHABORT в положение ON, увидел улучшение производительности и пришел к тем же выводам, что и другие. Что касается индексированных представлений и вычисляемых столбцов, мне неясно. В одном месте указывается, что параметры SET должны иметь конкретные значения, если операция INSERT, UPDATE или DELETE изменяет значения данных, хранящиеся в них. В другом месте они утверждают, что оптимизатор будет игнорировать индексы для «любого запроса», который ссылается на указанное индексированное представление или вычисляемый столбец. Верны ли они, или это действительно "любые данные, модифицирующие запрос"?
Мдойл
1

Просто была эта проблема. Как здесь говорили, первопричина - несколько планов запросов, один из которых неоптимальный. Я просто хотел убедиться, что ARITHABORT действительно может сам вызвать проблему (поскольку запрос, с которым у меня были проблемы, не имел параметров, что исключает анализ параметров из уравнения).

Алан Д. Нельсон
источник
1

Это напоминает мне ту же проблему, с которой я столкнулся в SQL Server 2008 дней. В нашем случае мы внезапно обнаружили, что одна работа sql внезапно замедлилась (обычно на несколько секунд, а теперь - на 9+ минут), работа должна получить доступ к связанному серверу, мы добавили параметр ARITHABORT на шаге задания, и это казалось проблемой было решено в течение нескольких дней, а затем вернулся.

Позже мы открыли тикет с поддержкой MS, и первоначально они тоже не смогли его найти, и тикет был передан очень старшей команде PFE, и два PFE поддержки попытались выяснить эту проблему.

Последняя причина заключается в том, что учетные данные пользователя (для выполнения шага задания) не могут получить доступ к статистике базовых таблиц (на стороне связанного сервера), и, следовательно, план выполнения не оптимизируется.

Подробно, у пользователя нет разрешения на DBCC SHOW_STATISTICS (хотя пользователь может ВЫБРАТЬ из таблицы). Согласно MSDN , это правило разрешений изменяется после SQL 2012 SP1

Разрешения для SQL Server и базы данных SQL

Для просмотра объекта статистики пользователь должен владеть таблицей, либо пользователь должен быть членом предопределенной роли сервера sysadmin, предопределенной роли базы данных db_owner или предопределенной роли базы данных db_ddladmin.

SQL Server 2012 SP1 изменяет ограничения разрешений и позволяет пользователям с разрешением SELECT использовать эту команду. Обратите внимание, что следующие требования существуют для разрешений SELECT, достаточных для запуска команды:

Чтобы проверить эту проблему, нам просто нужно запустить профилировщик на связанном экземпляре на стороне сервера и включить некоторые события в разделе «Ошибки и предупреждения», как показано ниже.

введите описание изображения здесь

Надеюсь, что этот опыт может как-то помочь сообществу.

jyao
источник