Запрос, который выполняет много чтений, но план в порядке

У меня странное поведение при выполнении определенного запроса в SQL Server 2008 R2. У меня есть запрос, который выполняет 19 миллионов чтений и занимает очень много времени, и когда я пытаюсь проверить его кэшированный план, план в порядке, без каких-либо проблем.

После выполнения DBCC FREEPROCCACHE тот же запрос выполняет 400 операций чтения (что занимает 16 мс). Вывод состоит в том, что каким-то образом запрос выполняется с неправильным планом, но это не та информация, которую я получил от SQL Server.

Кто-нибудь знает, что происходит? Найдите ниже запросы, которые я использовал для извлечения плана:

SELECT
sqltext.TEXT,
sqlplan.query_plan,
req.session_id [Session ID],
p.kpid [Thread ID],
p.program_name,
req.status,
req.command,
req.cpu_time,
req.logical_reads,
req.blocking_session_id,
req.transaction_id,
req.total_elapsed_time,
req.wait_resource
FROM sys.dm_exec_requests req inner join
     sys.sysprocesses p on req.session_id = p.spid
     CROSS APPLY sys.dm_exec_query_plan(req.plan_handle) AS sqlplan
     CROSS APPLY sys.dm_exec_sql_text(req.sql_handle) AS sqltext

А также

SELECT db.name,
cp.objtype AS ObjectType,
OBJECT_NAME(st.objectid,st.dbid) AS ObjectName,
cp.usecounts AS ExecutionCount,
st.TEXT AS QueryText,
qp.query_plan AS QueryPlan
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS st 
INNER JOIN sys.sysdatabases db on st.dbid = db.dbid
where st.TEXT like '%part_of_query%'

Другая информация заключается в том, что план запроса остается неизменным до и после команды освобождения кеша.

Изображение плана выполнения


person bigster    schedule 13.08.2014    source источник
comment
Вы можете рассмотреть вопрос об этом и на dba.stackexchange.com, если вы еще этого не сделали.   -  person shree.pat18    schedule 13.08.2014
comment
Я только что так и сделал, спасибо за совет.   -  person bigster    schedule 13.08.2014
comment
опубликуйте вывод STATISTICS IO для двух прогонов.   -  person Remus Rusanu    schedule 13.08.2014
comment
То есть вы говорите, что кэшированный план из обоих прогонов точно такой же?   -  person Thomas Stringer    schedule 13.08.2014
comment
Да, именно это я и говорю, и вот что странно.   -  person bigster    schedule 13.08.2014
comment
Пожалуйста, отредактируйте эту информацию в своем вопросе, а не размещайте в комментариях.   -  person Mark Storey-Smith    schedule 13.08.2014
comment
Даже если форма плана может остаться прежней или план может быть использован повторно, он может страдать из-за перехвата параметров или искаженной статистики. Тот факт, что это один и тот же план, не означает, что это правильный план. Если бы вы могли опубликовать фактические планы обоих казней, это было бы очень полезно.   -  person    schedule 13.08.2014
comment
Оба этих запроса будут извлекать только временной план компиляции (предполагаемый план). Вам нужно будет оценить фактический план выполнения. Когда вы это сделаете, вы, вероятно, увидите, что это случай плохого анализа параметров версии.   -  person SQLRNNR    schedule 13.08.2014
comment
Как оценить фактический план выполнения? Я думал, что первый запрос даст мне план, который выполняется ...   -  person bigster    schedule 13.08.2014


Ответы (1)


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

Устаревшая статистика распределения также может привести к такому поведению. А также фрагментированные индексы. Вероятно, есть и другие возможности - не видя фактического плана выполнения, угадывание может продолжаться бесконечно.

Но вы можете попробовать добавить в запрос параметр optimize for unknown и посмотреть, поможет ли это.

person Roger Wolf    schedule 13.08.2014