2013-12-20 3 views
13

Я прочитал много статей о параметрах нюхания, но не ясно, хорошо это или плохо. Кто-нибудь может объяснить это простым примером.SQL Server - параметр sniffing

Есть ли способ автоматически определить, что неправильный план был назначен для конкретного заявления?

Заранее спасибо.

+0

Проверьте [это] (http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx). – Sergi

+0

@Sergi: Это относится и к специальным заявлениям? – user3104183

+0

, когда фактическое число строк возвращается для каждого параметра почти одинаковое. Не так много вариаций, то можно позволить себе игнорировать его. Также я думаю, что объявление фиктивной переменной лучше. Я не прав? – KumarHarsh

ответ

20

Это хорошо, но иногда бывает плохо.

Параметр sniffing - это оптимизатор запросов, использующий значение предоставленного параметра для определения наилучшего плана запроса. Один из многих вариантов и один, который довольно легко понять, это то, что вся таблица должна быть отсканирована, чтобы получить значения, или если она будет быстрее с использованием запросов индекса. Если значение в вашем параметре очень избирательно, оптимизатор, вероятно, построит план запроса с помощью запросов, и если он не будет выполнять запрос, сканирование вашей таблицы.

План запроса затем кэшируется и повторно используется для последовательных запросов, имеющих разные значения. Плохая часть параметра sniffing - это когда кешированный план не является лучшим выбором для одного из этих значений.

Образец данных:

create table T 
(
    ID int identity primary key, 
    Value int not null, 
    AnotherValue int null 
); 

create index IX_T_Value on T(Value); 

insert into T(Value) values(1); 

insert into T(Value) 
select 2 
from sys.all_objects; 

T таблица с пару тысяч строк с кластерным индексом, не по значению. Существует одна строка, где значение равно 1, а остальное значение - 2.

Пример запроса:

select * 
from T 
where Value = @Value; 

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

Когда понюхал значение 1 план запроса будет выглядеть следующим образом:

enter image description here

И когда понюхала значение 2 это будет выглядеть следующим образом:

enter image description here

Плохая часть параметра sniffing в этом случае происходит, когда план запроса построен, обнюхивая 1, но выполняемый позже с значение 2.

enter image description here

Вы можете видеть, что ключ поиска был выполнен 2352 раз. Лучшим выбором будет сканирование.

Подводя итог, я бы сказал, что параметр sniffing - это хорошая вещь, которую вы должны попытаться сделать как можно больше, используя параметры для своих запросов. Иногда это может пойти не так, и в таких случаях это, скорее всего, связано с искаженными данными, которые воюют с вашей статистикой.

Update:

Вот запрос на пару DMV-х годов, которые вы можете использовать, чтобы найти то, что запросы являются наиболее дорогими в вашей системе. Измените в порядке заказа, чтобы использовать разные критерии для того, что вы ищете. Я думаю, что TotalDuration - хорошее место для начала.

set transaction isolation level read uncommitted; 

select top(10) 
    PlanCreated  = qs.creation_time, 
    ObjectName  = object_name(st.objectid), 
    QueryPlan   = cast(qp.query_plan as xml), 
    QueryText   = substring(st.text, 1 + (qs.statement_start_offset/2), 1 + ((isnull(nullif(qs.statement_end_offset, -1), datalength(st.text)) - qs.statement_start_offset)/2)), 
    ExecutionCount = qs.execution_count, 
    TotalRW   = qs.total_logical_reads + qs.total_logical_writes, 
    AvgRW    = (qs.total_logical_reads + qs.total_logical_writes)/qs.execution_count, 
    TotalDurationMS = qs.total_elapsed_time/1000, 
    AvgDurationMS  = qs.total_elapsed_time/qs.execution_count/1000, 
    TotalCPUMS  = qs.total_worker_time/1000, 
    AvgCPUMS   = qs.total_worker_time/qs.execution_count/1000, 
    TotalCLRMS  = qs.total_clr_time/1000, 
    AvgCLRMS   = qs.total_clr_time/qs.execution_count/1000, 
    TotalRows   = qs.total_rows, 
    AvgRows   = qs.total_rows/qs.execution_count 
from sys.dm_exec_query_stats as qs 
    cross apply sys.dm_exec_sql_text(qs.sql_handle) as st 
    cross apply sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) as qp 
--order by ExecutionCount desc 
--order by TotalRW desc 
order by TotalDurationMS desc 
--order by AvgDurationMS desc 
; 
+0

Есть ли способ автоматически обнаружить, что неправильный план был назначен для конкретного заявления? Простой и лаконичный, спасибо! – user3104183

+1

@ user3104183 Да, вы можете использовать dmv [sys.dm_exec_query_stats] (http://msdn.microsoft.com/en-us/library/ms189741.aspx), чтобы посмотреть, какие запросы возникают в вашей системе. –

+0

как? Должен ли я искать утверждения, которые имеют один и тот же запрос хеш, но разные хеши запроса плана, с большим количеством логических чтений? – user3104183

0

Да, иногда это хорошо или плохо.

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

Я обнаружил, что в моей ситуации оптимизатор запросов использует старый план запросов вместо создания нового плана запроса. Оптимизатор запросов использовал старый запрос из кеша запросов. Я создал очень интересное сообщение о параметрах Sniffing. Пожалуйста, посетите этот адрес: http://www.dbrnd.com/2015/05/sql-server-parameter-sniffing/

Смежные вопросы