Как сохранить план выполнения запроса, чтобы его можно было использовать позже - PullRequest
4 голосов
/ 02 сентября 2010

Мои приложения запускают запросы к базе данных сервера sql.

Во многих случаях я вижу преимущество плана выполнения: например, я впервые нажимаю кнопку на

SELECT * from Tasks
WHERE IdUser = 24 AND
  DATE < '12/12/2010' and DATE > '01/01/2010'

это занимает 15 секунд в первый раз, 8 секунд - в следующий раз.

РЕДАКТИРОВАТЬ: Я ИСПОЛЬЗУЮ ПАРАМЕТРИРОВАННЫЕ ЗАПРОСЫ.

Таким образом, у меня есть улучшение на 7 секундво второй раз.

Теперь, когда я снова запускаю приложение (поэтому устанавливаю новое соединение с базой данных), первый раз это займет 15 секунд, второй раз 7 ...

Как этоМожно ли заставить SQL Server хранить планы выполнения, хотя бы запомнить их на те же дни?Или, однако, как я могу получить выгоду от уже рассчитанных планов выполнения?Если разные пользователи выполняют один и тот же запрос, это способ сообщить серверу sql, что он достаточно умен, чтобы использовать один и тот же план выполнения, даже если в этом случае, вероятно, IdUser будет другим.Может быть, следующее выполнение запроса будет иметь разные значения MinDate и MaxDate, но повлияет ли это на план запроса?

Ответы [ 3 ]

2 голосов
/ 02 сентября 2010

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

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

Итак, поэтому:

  • будьте последовательны в своих запросах - всегда пишите вещи одинаково (следите за заглавными буквами / некапитализацией, пробелами, dbo. префиксами и т. Д.)

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

  • старайтесь избегать SELECT * - это означает, что оптимизатор запросов имеет меньше опций - поскольку вам нужны все столбцы, он обычно должен сканировать кластеризованный индекс. Если вы укажете три, пять, шесть столбцов, которые вам действительно нужны, есть вероятность, что может существовать индекс, охватывающий запрос (содержащий все интересующие вас столбцы), и, следовательно, анализ запроса может использовать этот индекс и выполнить сканирование индекса / поиск индекса по этому (и повторное использование этого плана).

Так что вместо вашего SQL сейчас используйте это вместо:

SELECT (list of fields)
FROM dbo.MYTasks 
WHERE DATE < @EndDate and DATE > @StartDate

Это должно значительно увеличить повторное использование плана запросов.

2 голосов
/ 02 сентября 2010

Использование параметризованных запросов для максимизации вероятности кэширования плана

SELECT * from MYTasks 
WHERE IdUser = @UserId AND DATE < @enddate and DATE > @startdate

SQL Server выполняет автоматическую параметризацию, но может быть довольно консервативно в этом.

Вы можете получить некоторую информациюв план повторного использования из следующих

SELECT usecounts, cacheobjtype, objtype, text, query_plan, value as set_options
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) 
CROSS APPLY sys.dm_exec_query_plan(plan_handle) 
cross APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
where text like '%MYTasks%' and attribute='set_options'
0 голосов
/ 02 сентября 2010

Вы запускали SQL Server Profiler? Если да, уверены ли вы, что при составлении оператора и создании планов выполнения уходит дополнительное время?

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

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

...