Основные сведения о структурах планов

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

ПримечаниеПримечание

Структура плана может использоваться только в выпусках SQL Server Standard Edition, Developer Edition, Evaluation Edition и Enterprise Edition, однако структуры плана видны в любой версии. Можно также присоединить базу данных, содержащую структуры планов, к любой версии. Структуры планов остаются нетронутыми при восстановлении или присоединении базы данных к обновленной версии SQL Server 2008.

Сопоставление структур планов с запросами

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

  • Структура плана OBJECT соответствует запросам, выполняемым в контексте хранимых процедур языка Transact-SQL, определяемых пользователем скалярных функций, определяемых пользователем функций с несколькими инструкциями, возвращающих табличные значения, и триггеров DML.

  • Структура плана SQL соответствует запросам, выполняющимся в контексте изолированных инструкций Transact-SQL и пакетов, не входящих ни в один объект базы данных. Структуры планов SQL также можно использовать для соответствия запросам с параметрами.

  • Структура плана TEMPLATE соответствует изолированным параметризованным запросам. Эти структуры планов используются для переопределения текущего параметра PARAMETERIZATION инструкции SET базы данных для класса запросов. Дополнительные сведения см. в разделах Простая параметризация и Принудительная параметризация.

Дополнительные сведения см. в разделе Как SQL Server сопоставляет структуры планов запросам.

Структуры планов OBJECT

Рассмотрим следующую хранимую процедуру, принимающую параметр @Country_region, которая существует в приложении базы данных, развертываемом для базы данных База данных AdventureWorks2008R2.

CREATE PROCEDURE Sales.GetSalesOrderByCountry (@Country_region nvarchar(60))
AS
BEGIN
    SELECT *
    FROM Sales.SalesOrderHeader AS h, Sales.Customer AS c, 
        Sales.SalesTerritory AS t
    WHERE h.CustomerID = c.CustomerID
        AND c.TerritoryID = t.TerritoryID
        AND CountryRegionCode = @Country_region
END;

Предполагается, что эта хранимая процедура скомпилирована и оптимизирована для значения @Country_region = N'AU' (Австралия). Однако поскольку из Австралии поступает относительно немного заказов на продажу, производительность падает при выполнении запроса со значениями данного параметра для стран с большим количеством заказов. Так как страна, из которой поступает больше всего заказов на продажу, — США, план запроса, сформированный для значения @Country_region = N'US', вероятно, обеспечит лучшую производительность для всех возможных значений параметра @Country_region.

Чтобы решить эту проблему, измените хранимую процедуру и добавьте подсказку OPTIMIZE FOR в запрос. Однако так как хранимая процедура находится в развернутом приложении, напрямую менять код приложения нельзя. Вместо этого можно создать следующую структуру плана в базе данных База данных AdventureWorks2008R2.

sp_create_plan_guide 
@name = N'Guide1',
@stmt = N'SELECT *FROM Sales.SalesOrderHeader AS h,
        Sales.Customer AS c,
        Sales.SalesTerritory AS t
        WHERE h.CustomerID = c.CustomerID 
            AND c.TerritoryID = t.TerritoryID
            AND CountryRegionCode = @Country_region',
@type = N'OBJECT',
@module_or_batch = N'Sales.GetSalesOrderByCountry',
@params = NULL,
@hints = N'OPTION (OPTIMIZE FOR (@Country_region = N''US''))'

При выполнении запроса, указанного в инструкции sp_create_plan_guide, этот запрос изменяется до оптимизации: в него добавляется предложение OPTIMIZE FOR (@Country = N''US'').

Структуры планов SQL

Структуры планов SQL применяются к изолированным инструкциям Transact-SQL и пакетам. Часто эти инструкции передаются приложением с помощью хранимой процедуры sp_executesql. Например, рассмотрим следующий изолированный пакет:

SELECT TOP 1 * FROM Sales.SalesOrderHeader ORDER BY OrderDate DESC;

Чтобы избежать создания параллельного плана выполнения для этого запроса, создайте приведенную ниже структуру плана и присвойте подсказке запроса MAXDOP значение 1 в параметре @hints.

sp_create_plan_guide 
@name = N'Guide2', 
@stmt = N'SELECT TOP 1 * FROM Sales.SalesOrderHeader ORDER BY OrderDate DESC',
@type = N'SQL',
@module_or_batch = NULL, 
@params = NULL, 
@hints = N'OPTION (MAXDOP 1)';
ПримечаниеПримечание

Пакет, содержащий инструкцию, по которой нужно создать структуру плана, не может содержать инструкцию USE database.

Важное примечаниеВажно!

Значения, передаваемые для аргументов @module_or_batch и @params инструкции sp_create_plan guide, должны соответствовать тексту настоящего запроса. Дополнительные сведения см. в разделах sp_create_plan_guide (Transact-SQL) и Использование приложения SQL Server Profiler для создания и проверки структур планов.

Кроме того, структуры планов SQL можно создавать для запросов с той же параметризованной формой, если параметр базы данных PARAMETERIZATION инструкции SET имеет значение FORCED либо если создана структура плана TEMPLATE, определяющая, что класс запросов должен быть параметризован. Дополнительные сведения см. в разделе Конструирование структур планов для параметризованных запросов.

Структуры планов TEMPLATE

Структуры планов TEMPLATE используются для переопределения поведения параметризации в отдельных формах запросов. Структуры планов TEMPLATE создаются в одной из следующих ситуаций.

  • Параметр базы данных PARAMETERIZATION инструкции SET хранит значение FORCED, но есть запросы, которые желательно скомпилировать в соответствии с правилами простой параметризации.

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

Дополнительные сведения см. в разделе Указание механизма параметризации запросов с помощью структур плана.

В приведенном ниже примере создается структура плана, которой сопоставляется запрос заданной параметризованной формы и которая вынуждает SQL Server параметризовать поступающие запросы. Два приведенных ниже запроса являются синтаксическими эквивалентами, однако различаются своими значениями постоянных литералов.

SELECT * FROM AdventureWorks2008R2.Sales.SalesOrderHeader AS h
INNER JOIN AdventureWorks2008R2.Sales.SalesOrderDetail AS d 
    ON h.SalesOrderID = d.SalesOrderID
WHERE h.SalesOrderID = 45639;

SELECT * FROM AdventureWorks2008R2.Sales.SalesOrderHeader AS h
INNER JOIN AdventureWorks2008R2.Sales.SalesOrderDetail AS d 
    ON h.SalesOrderID = d.SalesOrderID
WHERE h.SalesOrderID = 45640;

Ниже представлена структура плана для параметризованного запроса.

EXEC sp_create_plan_guide 
    @name = N'TemplateGuide1',
    @stmt = N'SELECT * FROM AdventureWorks2008R2.Sales.SalesOrderHeader AS h
              INNER JOIN AdventureWorks2008R2.Sales.SalesOrderDetail AS d 
                  ON h.SalesOrderID = d.SalesOrderID
              WHERE h.SalesOrderID = @0',
    @type = N'TEMPLATE',
    @module_or_batch = NULL,
    @params = N'@0 int',
    @hints = N'OPTION(PARAMETERIZATION FORCED)';

В предыдущем примере значение аргумента @stmt является параметризованной формой запроса. Единственным надежным способом выяснения указанного значения для использования в процедуре sp_create_plan_guide является использование системной хранимой процедуры sp_get_query_template. С помощью следующего сценария можно выполнить параметризованный запрос, а затем создать на его основе структуру плана.

DECLARE @stmt nvarchar(max);
DECLARE @params nvarchar(max);
EXEC sp_get_query_template 
    N'SELECT * FROM AdventureWorks2008R2.Sales.SalesOrderHeader AS h
      INNER JOIN AdventureWorks2008R2.Sales.SalesOrderDetail AS d 
          ON h.SalesOrderID = d.SalesOrderID
      WHERE h.SalesOrderID = 45639;',
    @stmt OUTPUT, 
    @params OUTPUT
EXEC sp_create_plan_guide N'TemplateGuide1', 
    @stmt, 
    N'TEMPLATE', 
    NULL, 
    @params, 
    N'OPTION(PARAMETERIZATION FORCED)';
Важное примечаниеВажно!

Значения постоянных литералов аргумента @stmt, передаваемого в процедуру sp_get_query_template, определяют тип данных для аргумента, заменяющего указанные литералы. Это влияет на совпадение структур планов. Возможно, придется создать несколько структур плана для обработки различных диапазонов значений аргумента.

Структуры планов TEMPLATE также можно использовать совместно со структурами планов SQL. Например, можно создать структуру плана TEMPLATE, чтобы убедиться, что класс запросов будет параметризован. Затем можно создать структуру плана SQL для параметризованной формы запроса.

Применение фиксированного плана запроса к структуре плана

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

В следующем примере создается структура плана для простой нерегламентированной инструкции SQL. Требуемый план запроса для этой инструкции представлен в структуре плана путем указания XML Showplan для запроса непосредственно в параметре @hints . В примере сначала выполняется инструкция SQL для создания плана в кэше планов. В этом примере допустим, что созданный план является желаемым планом и не требуется дополнительной настройки запросов. Данные XML Showplan для запроса необходимо получить с помощью запроса к динамическим административным представлениям sys.dm_exec_query_stats, sys.dm_exec_sql_text и sys.dm_exec_text_query_plan и присвоить переменной @xml_showplan. Переменная @xml_showplan затем передается инструкции sp_create_plan_guide в параметре @hints. Также можно создать структуру плана в кэше планов, используя хранимую процедуру sp_create_plan_guide_from_handle.

USE AdventureWorks2008R2;
GO
SELECT City, StateProvinceID, PostalCode FROM Person.Address ORDER BY PostalCode DESC;
GO
DECLARE @xml_showplan nvarchar(max);
SET @xml_showplan = (SELECT query_plan
    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, DEFAULT, DEFAULT) AS qp
    WHERE st.text LIKE N'SELECT City, StateProvinceID, PostalCode FROM Person.Address ORDER BY PostalCode DESC;%');

EXEC sp_create_plan_guide 
    @name = N'Guide1_from_XML_showplan', 
    @stmt = N'SELECT City, StateProvinceID, PostalCode FROM Person.Address ORDER BY PostalCode DESC;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = @xml_showplan;
GO

Проверка структур планов после обновления

Рекомендуется переоценить и протестировать определения структур планов при обновлении приложения для работы с новым выпуском SQL Server. Требования к настройке производительности и поведение сопоставления структур планов могут меняться. Хотя недопустимая структура плана не приведет к сбою при выполнении запроса, план будет скомпилирован без использования структуры, что не рекомендуется. После обновления базы данных до версии SQL Server 2008 рекомендуется выполнить следующие действия.

  • Проверьте существующие структуры планов с помощью функции sys.fn_validate_plan_guide.

  • В приложении Приложение SQL Server Profiler проверьте наличие планов без структуры за определенное время с помощью события Plan Guide Unsuccessful.