Использование табличной подсказки FORCESEEK

Табличная подсказка FORCESEEK принуждает оптимизатор запросов использовать в качестве пути доступа к данным, указанным в запросе таблиц или представлений, только операцию поиска в индексе. Данная табличная подсказка используется для замещения выбранного оптимизатором запросов плана по умолчанию, чтобы избежать вызванного неэффективным планом падения производительности. Например, если план содержит операторы просмотра таблицы или индекса, соответствующие таблицы вызывают большое количество считываний во время выполнения запроса, что наблюдается на выходе STATISTICS IO. В этом случае принуждение использования операции поиска индекса может обеспечить лучшую производительность при выполнении запроса. Это особенно актуально, если основываясь на неточных оценках мощности или затрат, оптимизатор использует много операций просмотра во время компиляции плана.

Табличная подсказка FORCESEEK может использоваться как с операциями поиска в кластеризованном, так и некластеризованном индексе. Ее можно указывать для любой таблицы или представления в предложении FROM инструкции SELECT и в предложении FROM <table_source> инструкций UPDATE и DELETE.

ПредупреждениеВнимание!

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

Оценка планов запросов на применимость табличной подсказки FORCESEEK

Табличная подсказка FORCESEEK может быть полезна, если в плане запроса используются операторы просмотра индекса таблиц или представлений, но оператор поиска индекса может оказаться более эффективным. Рассмотрим следующий запрос и план выполнения.

USE AdventureWorks2008R2;
GO
SELECT *
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d 
    ON h.SalesOrderID = d.SalesOrderID 
WHERE h.TotalDue > 100
AND (d.OrderQty > 5 OR d.LineTotal < 1000.00);
GO

По плану выполнения видно, что для доступа к данным в обеих таблицах оптимизатор запросов выбрал оператор просмотра кластеризованного индекса.

План выполнения с операторами Clustered Index Scan

Используя табличную подсказку FORCESEEK можно заставить оптимизатор запросов выполнить по отношению к таблице Sales.SalesOrderDetail операцию поиска как показано в следующем запросе.

USE AdventureWorks2008R2;
GO
SELECT *
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d WITH (FORCESEEK)
    ON h.SalesOrderID = d.SalesOrderID 
WHERE h.TotalDue > 100
AND (d.OrderQty > 5 OR d.LineTotal < 1000.00);
GO

Следующий план выполнения демонстрирует результаты использования подсказки FORCESEEK в запросе. Для доступа к данным таблицы Sales.SalesOrderDetail используется операция поиска в кластеризованном индексе.

План выполнения с операторами Clustered Index Seek

Поддержка объединения и пересечения индексов

Подсказка FORCESEEK поддерживает объединение и пересечение индексов. Применение подсказки делает более вероятным использование этих методов оптимизатором запросов. Чтобы избежать увеличения времени компиляции простых запросов, объединение и пересечение индексов обычно выбирается по правилам, при том что принимаются в расчет мощность и избирательность столбцов. Однако при использовании подсказки FORCESEEK эти правила не учитываются и всегда используются эти методы. Например, рассмотрим следующий запрос:

SELECT * FROM T WITH(FORCESEEK) WHERE T.a = 1 AND T.b = 2;

План пересечения индексов может быть выбран при наличии отдельных, некластеризованных индексов столбцов a и b таблицы T. Таким образом, план содержит операцию поиска в некластеризованном индексе столбца a, операцию поиска в некластеризованном индексе столбца b и выполняет пересечение результирующих наборов ключей индекса перед операцией поиска в базовой таблице.

В следующем примере выбран план объединения индексов. План содержит операцию поиска в индексе столбца a, операцию поиска в индексе столбца b и выполняет объединение результирующих наборов ключей индекса перед операцией поиска в базовой таблице.

SELECT * FROM T WITH(FORCESEEK) WHERE T.a = 1 OR T.b = 2;

Использование подсказки FORCESEEK в запросах с LIKE или IN

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

В следующем примере демонстрируется применение подсказки FORCESEEK для принуждения оптимизатора запросов к выполнению операции поиска в индексе вместо операции просмотра таблиц при наличии предикатов поиска LIKE или IN. Для просмотра планов выполнения запросов нажмите кнопку Включить действительный план выполнения на панели инструментов до запуска примера.

USE tempdb;GODROP TABLE t;GOCREATE TABLE t(i int UNIQUE, j int, vc varchar(100));CREATE INDEX t_vc ON t(vc);GODECLARE @p1 int, @p2 int, @p3 int, @p4 int, @p5 int;SELECT * FROM t WHERE i IN (@p1, @p2, @p3, @p4, @p5);GODECLARE @p1 int, @p2 int, @p3 int, @p4 int, @p5 int;SELECT * FROM t WITH (FORCESEEK) WHERE i IN (@p1, @p2, @p3, @p4, @p5);GOSELECT * FROM t WHERE vc LIKE 'Test%';GOSELECT * FROM t WITH (FORCESEEK) WHERE vc LIKE 'Test%';GODECLARE @vc varchar(100);SELECT * FROM t WHERE vc LIKE @vc;GODECLARE @vc varchar(100);SELECT * FROM t WITH (FORCESEEK) where vc like @vc;GO

Использование подсказки FORCESEEK для представлений

Табличная подсказка FORCESEEK может использоваться как совместно, так и без подсказки индекса. Применение подсказки FORCESEEK к представлению или индексированному представлению приводит к ее рекурсивному распространению на все таблицы в расширенной версии представления. Подсказка индекса, при наличии, не учитывается. Если базовые таблицы не содержат по крайней мере по одному индексу каждая, план не будет найден и будет возвращена ошибка 8622.

При совместном использовании подсказок FORCESEEK и NOEXPAND для ссылки на индексированное представление оно используется без предварительного раскрытия. Подсказка FORCESEEK применяется непосредственно к индексированному представлению, с которым можно обращаться так же, как и с таблицей.

Если применить подсказку FORCESEEK к ссылочной таблице, ссылочная таблица не сможет участвовать в сопоставлении индексированного представления. Однако другие планы запроса, незатронутые подсказкой FORCESEEK, могут участвовать в сопоставлении индексированного представления. Это похоже на сопоставление индексированного представления при использовании подсказок INDEX.

Советы и рекомендации

Рекомендуются следующие методы:

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

    Обновляемая статистика позволяет оптимизатору точно оценить стоимость разных планов запросов и выбрать высококачественный план. Поэтому рекомендуется установить параметры AUTO_CREATE_STATISTICS и AUTO_UPDATE_STATISTICS в значение ON (по умолчанию) для каждой пользовательской базы данных. Также можно вручную обновить статистику по таблице или представлению с помощью инструкции UPDATE STATISTICS.

  • Оцените запрос на наличие элементов, которые могут вызвать неточную оценку их количества или оценку затрат и по возможности удалите эти элементы. Например, замените локальные переменные параметрами или литералами и ограничьте использование в запросе многооператорных функций, возвращающих табличное значение, и табличных переменных. Дополнительные сведения о других элементах, на которые необходимо обратить внимание см. в разделе Статистики, используемые оптимизатором запросов Microsoft SQL Server 2005.

  • Не используйте без необходимости подсказку INDEX в сочетании с FORCESEEK. Если подсказка FORCESEEK сама по себе формирует адекватный план, использование дополнительной подсказки INDEX может значительно ограничить свободу выбора оптимизатора. Кроме того, подсказка INDEX приведет к ошибке запроса при изменении физической схемы таблицы, связанном с удалением указанного в подсказке индекса. Напротив, если в таблице, к которой применяется подсказка FORCESEEK, существует по крайней мере один доступный для использования индекс, запрос будет компилироваться даже в процессе изменения структур индекса.

  • Не используйте подсказку INDEX (0) вместе с подсказкой FORCESEEK. Подсказка INDEX (0) запускает принудительный просмотр базовой таблицы. При использовании совместно с FORCESEEK план не будет найден и будет возвращена ошибка 8622.

  • Не используйте подсказку в запросе USE PLAN вместе с подсказкой FORCESEEK. Подсказка FORCESEEK в этом случае не будет обрабатываться.