Параметр Sniffing (или Spoofing) в SQL Server
некоторое время назад у меня был запрос, который я запустил довольно много для одного из моих пользователей. Он все еще развивался и настраивался, но в конечном итоге он стабилизировался и работал довольно быстро, поэтому мы создали хранимую процедуру из него.
пока все нормально.
хранимая процедура, однако, была медленной собакой. Нет существенной разницы между запросом и proc, но изменение скорости было массовым.
[фон, мы запускаем SQL Server 2005.]
дружелюбный местный DBA (который больше не работает здесь) взглянул на хранимую процедуру и сказал: "спуфинг параметров!"(Edit: хотя кажется, что это, возможно, также известно как "нюхание параметров", что может объяснить нехватку хитов Google, когда я пытался его найти.)
мы абстрагировали часть хранимой процедуры во вторую, обернули вызов этого нового внутреннего proc в уже существующий внешний, называемый внешним, и, Эй, престо, это было так же быстро, как и оригинал запрос.
Итак, что дает? Может кто-нибудь объяснить спуфинг параметров?
бонус за
- подчеркивая, как этого избежать
- предлагая, как распознать возможную причину
- обсудите альтернативные стратегии, например, статистику, индексы, ключи, для смягчения ситуации
8 ответов:
FYI-вы должны быть осведомлены о чем-то еще, когда вы работаете с SQL 2005 и храните procs с параметрами.
среда SQL Server будет составить план выполнения хранимой proc и с первым параметром, который используется. Так что если вы запустите это:
usp_QueryMyDataByState 'Rhode Island'план выполнения будет работать с данными небольшого государства. Но если кто-то оборачивается и бежит:
usp_QueryMyDataByState 'Texas'план выполнения, разработанный для данных размера Род-Айленда, может быть не столь эффективным с помощью Данные размером с Техас. Это может привести к неожиданным результатам при перезапуске сервера, потому что вновь созданный план выполнения будет нацелен на любой параметр, который используется в первую очередь - не обязательно лучший. План не будет перекомпилирован, пока не будет большой причины для этого, например, если статистика будет перестроена.
здесь появляются планы запросов, и SQL Server 2008 предлагает множество новых функций, которые помогают DBAs закрепить конкретный план запроса на месте в долгосрочной перспективе независимо от того, что сначала вызываются параметры.
меня беспокоит то, что когда вы перестроили свой сохраненный proc, вы заставили план выполнения перекомпилироваться. Вы вызвали его с вашим любимым параметром, и тогда, конечно, это было быстро, но проблема, возможно, не была сохранена proc. Возможно, сохраненный proc был перекомпилирован в какой-то момент с необычным набором параметров и, следовательно, неэффективным планом запроса. Возможно, вы ничего не исправили, и вы можете столкнуться с той же проблемой в следующий раз время перезагрузки сервера или перекомпиляции плана запроса.
Да, я думаю, что вы имеете в виду обнюхивание параметров, которое является методом, который оптимизатор SQL Server использует, чтобы попытаться выяснить значения/диапазоны параметров, чтобы он мог выбрать лучший план выполнения для вашего запроса. В некоторых случаях SQL Server плохо справляется с параметром sniffing и не выбирает лучший план выполнения для запроса.
Я считаю, что эта статья в блогеhttp://blogs.msdn.com/queryoptteam/archive/2006/03/31/565991.aspx имеет хорошее объяснение.
Это кажется, что дБА в своем примере выбрал вариант № 4 запрос на другой sproc отдельного процессуального контексте.
вы могли бы также использовать С перекомпиляция на оригинальном sproc или использовал оптимизация опция на параметре.
простой способ ускорить это-переназначить входные параметры локальным параметрам в самом начале sproc, например
CREATE PROCEDURE uspParameterSniffingAvoidance @SniffedFormalParameter int AS BEGIN DECLARE @SniffAvoidingLocalParameter int SET @SniffAvoidingLocalParameter = @SniffedFormalParameter --Work w/ @SniffAvoidingLocalParameter in sproc body -- ...
по моему опыту, лучшим решением для обнюхивания параметров является "динамический SQL". Две важные вещи, чтобы отметить, что 1. вы должны использовать параметры в динамическом sql-запросе 2. вы должны использовать sp_executesql (а не sp_execute), который сохраняет план выполнения для каждого значения параметра
обнюхивание параметров-это метод, который SQL Server использует для оптимизации плана выполнения запроса для хранимой процедуры. При первом вызове хранимой процедуры SQL Server просматривает заданные значения параметров вызова и решает, какие индексы использовать на основе значений параметров.
поэтому, когда первый вызов содержит не очень типичные параметры, SQL Server может выбрать и сохранить неоптимальный план выполнения в отношении следующих вызовов сохраненного процедура.
вы можете обойти это либо
- используя
WITH RECOMPILE- копирование значений параметров в локальные переменные внутри хранимой процедуры и использование локальных значений в запросах.
Я даже слышал, что лучше вообще не использовать хранимые процедуры, а отправлять свои запросы непосредственно на сервер. Недавно я столкнулся с той же проблемой, где у меня еще нет реального решения. Для некоторых запросов помогает копирование в локальные vars возвращаясь к правильному плану выполнения, для некоторых запросов производительность ухудшается с локальными vars.
Мне все еще нужно провести дополнительные исследования о том, как SQL Server кэширует и повторно использует (неоптимальные) планы выполнения.
У меня была аналогичная проблема. План выполнения моей хранимой процедуры уходило 30-40 секунд. Я попытался использовать инструкции SP в окне запроса, и для их выполнения потребовалось несколько МС. Затем я разработал объявление локальных переменных в хранимой процедуре и перенос значений параметров в локальные переменные. Это сделало выполнение SP очень быстрым, и теперь тот же SP выполняется в течение нескольких миллисекунд вместо 30-40 секунд.
очень простой и сортировать, оптимизатор запросов использовать старый план запроса для часто выполняемых запросов. но на самом деле размер данных также увеличивается, поэтому в это время требуется новый оптимизированный план и все еще оптимизатор запросов, использующий старый план запроса. Это называется параметрическим обнюхиванием. Я напишу подробный пост об этом. Пожалуйста, посетите этот url: http://www.dbrnd.com/2015/05/sql-server-parameter-sniffing/
изменение процедуры хранения для выполнения в виде пакета должно увеличить скорость.
пакетный файл выберите именно:
exec ('select * from order where order id ='''+ @ordersID')вместо обычной хранимой процедуры выберите:
select * from order where order id = @ordersIDпросто передайте параметр как
nvarcharи вы должны получить более быстрые результаты.
Comments