Partilhar via


dicas de consulta (Transact-SQL)

Dicas de consulta especificam que as dicas indicadas devem ser usadas pela consulta. As dicas de consulta afetam todos os operadores na instrução. Se UNION estiver envolvida na consulta principal, só a última consulta envolvendo uma operação UNION poderá ter a cláusula OPTION. As dicas de consulta são especificadas como parte da cláusula OPTION. Se uma ou mais discas de consulta fizerem com que o otimizador de consulta não gere um plano válido, será emitido o erro 8622.

Observação sobre cuidadosCuidado

Como o otimizador de consulta do SQL Server seleciona, normalmente, o melhor plano de execução para uma consulta, recomendamos usar dicas apenas como último recurso para desenvolvedores e administradores de banco de dados experientes.

Aplica-se a:

DELETE

INSERT

SELECT

UPDATE

MERGE

Ícone de vínculo de tópicoConvenções de sintaxe de Transact-SQL

Sintaxe

<query_hint > ::= 
{ { HASH | ORDER } GROUP 
  | { CONCAT | HASH | MERGE } UNION 
  | { LOOP | MERGE | HASH } JOIN 
  | FAST number_rows 
  | FORCE ORDER 
  | MAXDOP number_of_processors 
  | OPTIMIZE FOR ( @variable_name { UNKNOWN | = literal_constant } [ , ...n ] )
  | OPTIMIZE FOR UNKNOWN
  | PARAMETERIZATION { SIMPLE | FORCED }
  | RECOMPILE
  | ROBUST PLAN 
  | KEEP PLAN 
  | KEEPFIXED PLAN
  | EXPAND VIEWS 
  | MAXRECURSION number 
  | USE PLAN N'xml_plan'| TABLE HINT ( exposed_object_name  [ , <table_hint> [ [, ]...n ] ] )<table_hint> ::=
[ NOEXPAND ] { 
    INDEX (index_value [ ,...n ] ) | INDEX = (index_value)
  | FASTFIRSTROW 
  | FORCESEEK
  | HOLDLOCK 
  | NOLOCK 
  | NOWAIT
  | PAGLOCK 
  | READCOMMITTED 
  | READCOMMITTEDLOCK 
  | READPAST 
  | READUNCOMMITTED 
  | REPEATABLEREAD 
  | ROWLOCK 
  | SERIALIZABLE 
  | TABLOCK 
  | TABLOCKX 
  | UPDLOCK 
  | XLOCK 
}

Argumentos

  • { HASH | ORDER } GROUP
    Especifica que as agregações descritas na cláusula GROUP BY, DISTINCT ou COMPUTE da consulta devem usar hash ou ordenação.

  • { MERGE | HASH | CONCAT } UNION
    Especifica que todas as operações UNION são executadas por mesclagem, hash ou concatenação de conjuntos de UNION. Se mais de uma dica de UNION for especificada, o otimizador de consulta selecionará a estratégia menos cara dentre as dicas especificadas.

  • { LOOP | MERGE | HASH } JOIN
    Especifica que todas as operações de junção são executadas por LOOP JOIN, MERGE JOIN ou HASH JOIN na consulta inteira. Se mais de uma dica de junção for especificada, o otimizador selecionará a estratégia de junção menos cara dentre as permitidas.

    Se, na mesma consulta, uma dica de junção for especificada também na cláusula FROM para um par de tabelas específico, essa dica de junção terá precedência na junção das duas tabelas, embora as dicas de consulta ainda devam ser consideradas. Portanto, a dica de junção para o par de tabelas pode restringir apenas a seleção de métodos de junção permitidos na dica de consulta. Para obter mais informações, consulte dicas de junção (Transact-SQL).

  • FAST number_rows
    Especifica que a consulta é otimizada para recuperação rápida dos primeiros number_rows. É um inteiro não negativo. Depois que o primeiro number_rows é retornado, a consulta continua a execução e produz seu conjunto de resultados completo.

  • FORCE ORDER
    Especifica que a ordem de junção indicada pela sintaxe de consulta é preservada durante a otimização da consulta. Usar FORCE ORDER não afeta o possível comportamento de reversão de função do otimizador de consulta. Para obter mais informações, consulte Compreendendo junções de hash.

    ObservaçãoObservação

    Em uma instrução MERGE, a tabela de origem é acessada antes da tabela de destino como a ordem de junção padrão, a menos que a cláusula WHEN SOURCE NOT MATCHED seja especificada. Especificar FORCE ORDER preserva esse comportamento padrão.

    Para obter informações sobre como o otimizador de consulta do SQL Server impõe a dica FORCE ORDER quando uma consulta contém uma exibição, consulte Resolução de exibição.

  • MAXDOP number
    Substitui a opção de configuração max degree of parallelism de sp_configure e o Administrador de Recursos na consulta que especifica essa opção. A dica de consulta MAXDOP pode exceder o valor configurado com sp_configure. Se MAXDOP exceder o valor configurado com o Administrador de Recursos, o Mecanismo de Banco de Dados usará o valor MAXDOP do Administrador de Recursos, descrito em ALTER WORKLOAD GROUP (Transact-SQL). Todas as regras semânticas usadas com a opção de configuração max degree of parallelism são aplicáveis ao usar a dica de consulta MAXDOP. Para obter mais informações, consulte Opção max degree of parallelism.

    Observação sobre cuidadosCuidado

    Se MAXDOP estiver definido como 0, o servidor escolherá o grau máximo de paralelismo. O servidor limita o DOP em 64 internamente.

  • OPTIMIZE FOR ( @variable\_name { UNKNOWN | = literal_constant } [ , ...n ] )
    Instrui o otimizador de consulta a usar um valor específico para uma variável local quando a consulta é compilada e otimizada. O valor só é usado durante a otimização, e não durante a execução das consultas.

    • @variable\_name
      É o nome de uma variável local usada em uma consulta para a qual um valor pode ser atribuído para uso com a dica de consulta OPTIMIZE FOR.

    • UNKNOWN
      Especifica que o otimizador de consulta usa dados estatísticos e não o valor inicial para determinar o valor de uma variável local durante a otimização da consulta.

    • literal_constant
      É um valor constante literal ao qual se atribui @variable\_name para uso com a dica de consulta OPTIMIZE FOR. literal_constant só é usado durante a otimização de consulta e não como o valor de @variable\_name durante a execução da consulta. literal_constant pode ser de qualquer tipo de dados do sistema SQL Server que possa ser expresso como uma constante literal. O tipo de dados de literal_constant deve ser implicitamente conversível no tipo de dados a que @variable\_name faz referência na consulta.

    OPTIMIZE FOR pode anular o comportamento de detecção de parâmetro padrão do otimizador ou pode ser usado na criação de guias de plano. Para obter mais informações, consulte Recompilando procedimentos armazenados e Otimizando consultas em aplicações implantadas com guias de plano.

  • OPTIMIZE FOR UNKNOWN
    Instrui o otimizador de consulta a usar dados estatísticos e não os valores iniciais para todas as variáveis locais quando a consulta é compilada e otimizada, incluindo parâmetros criados com parametrização forçada. Para obter mais informações sobre a parametrização forçada, consulte Parametrização forçada.

    Se OPTIMIZE FOR @variable\_name = literal_constant e OPTIMIZE FOR UNKNOWN forem usados na mesma dica de consulta, o otimizador de consulta usará a literal_constant especificada para um valor específico e UNKNOWN para o restante dos valores de variáveis. Os valores só são usados durante a otimização de consulta e não durante a execução das consultas.

  • PARAMETERIZATION { SIMPLE | FORCED }
    Especifica as regras de parametrização que o otimizador de consulta do SQL Server aplica à consulta quando ela é compilada.

    Observação importanteImportante

    A dica de consulta PARAMETERIZATION só pode ser especificada dentro de um guia de plano. Ela não pode ser especificada diretamente dentro de uma consulta.

    SIMPLE instrui o otimizador de consulta a tentar parametrização simples. FORCED instrui o otimizador de consulta a tentar parametrização forçada. A dica de consulta PARAMETERIZATION é usada para substituir a configuração atual da opção SET do banco de dados PARAMETERIZATION dentro de um guia de plano. Para obter mais informações, consulte Especificando comportamento de parametrização de consulta usando guias de plano.

  • RECOMPILE
    Instrui o Mecanismo de Banco de Dados do SQL Server a descartar o plano gerado para a consulta depois de sua execução, forçando o otimizador de consulta a recompilar um plano de consulta da próxima vez que a mesma consulta for executada. Sem especificar RECOMPILE, o Mecanismo de Banco de Dados armazena em cache os planos de consulta e os reutiliza. Ao compilar planos de consulta, a dica de consulta RECOMPILE usa os valores atuais de todas as variáveis locais na consulta e, se a consulta estiver dentro de um procedimento armazenado, os valores atuais serão passados para quaisquer parâmetros.

    RECOMPILE é uma alternativa útil à criação de um procedimento armazenado que utiliza a cláusula WITH RECOMPILE quando só um subconjunto de consultas dentro do procedimento armazenado, em vez de todo o procedimento armazenado, deve ser recompilado. Para obter mais informações, consulte Recompilando procedimentos armazenados. RECOMPILE também é útil para a criação de guias de plano. Para obter mais informações, consulte Otimizando consultas em aplicações implantadas com guias de plano.

  • ROBUST PLAN
    Força o otimizador de consulta a tentar um plano que trabalhe para o tamanho máximo de linhas potenciais, possivelmente às custas do desempenho. Quando a consulta é processada, tabelas e operadores intermediários podem precisar armazenar e processar linhas maiores do que qualquer uma das linhas de entrada. As linhas podem ser tão grandes que, às vezes, o operador particular não consegue processá-las. Se isso ocorrer, o Mecanismo de Banco de Dados produzirá um erro durante a execução da consulta. Usando ROBUST PLAN, você instrui o otimizador de consulta a não considerar nenhum plano de consulta que possa encontrar esse problema.

    Se tal plano não for possível, o otimizador de consulta retornará um erro, em vez de adiar a detecção de erros para a execução da consulta. Linhas podem conter colunas de tamanho variável. O Mecanismo de Banco de Dados permite definir linhas com o tamanho potencial máximo para além da capacidade de processamento do Mecanismo de Banco de Dados. Geralmente, apesar do tamanho potencial máximo, um aplicativo armazena linhas cujos tamanhos reais estão dentro dos limites de processamento do Mecanismo de Banco de Dados. Se o Mecanismo de Banco de Dados encontrar uma linha longa demais, será retornado um erro de execução.

  • KEEP PLAN
    Força o otimizador de consulta a relaxar o limite de recompilação estimado para uma consulta. O limite de recompilação estimado é o ponto no qual uma consulta é recompilada automaticamente quando o número calculado de alterações de colunas indexadas tiver sido efetuado em uma tabela por meio da execução da instrução UPDATE, DELETE, MERGE ou INSERT. Especificar KEEP PLAN assegura que uma consulta não seja recompilada tão freqüentemente como quando há várias atualizações em uma tabela.

  • KEEPFIXED PLAN
    Força o otimizador de consulta a não recompilar uma consulta devido a alterações nas estatísticas. Especificar KEEPFIXED PLAN assegura que uma consulta seja recompilada apenas se o esquema das tabelas subjacentes for alterado ou se sp_recompile for executado em relação a essas tabelas.

  • EXPAND VIEWS
    Especifica que as exibições indexadas são expandidas e o otimizador de consulta não considerará nenhuma exibição indexada como uma substituta de qualquer parte da consulta. Uma exibição é expandida quando o nome da exibição é substituído por sua definição no texto da consulta.

    Esta dica de consulta desabilita o uso direto de exibições indexadas e índices em exibições indexadas no plano de consulta.

    A exibição indexada só não será expandida se a exibição receber referência direta na parte SELECT da consulta e se WITH (NOEXPAND) ou WITH (NOEXPAND, INDEX ( index_value [ ,...n ])) for especificado. Para obter mais informações sobre a dica de consulta WITH (NOEXPAND), consulte FROM.

    Apenas as exibições na parte SELECT das instruções, inclusive aquelas nas instruções INSERT, UPDATE, MERGE e DELETE são afetadas pela dica.

  • MAXRECURSION number
    Especifica o número máximo de recursões permitido para a consulta. number é um inteiro não negativo entre 0 e 32767. Quando 0 é especificado, nenhum limite é aplicado. Se essa opção não for especificada, o limite padrão para o servidor será de 100.

    Quando o número especificado ou padrão de limite de MAXRECURSION é atingido durante a execução da consulta, a consulta é encerrada e um erro é retornado.

    Por causa desse erro, todos os efeitos da instrução são revertidos. Se a instrução for do tipo SELECT, poderão ser retornados resultados parciais ou nenhum resultado. Eventuais resultados parciais retornados podem não incluir todas as linhas em níveis de recursão acima do nível de recursão máximo especificado.

    Para obter mais informações, consulte WITH common_table_expression (Transact-SQL).

  • USE PLAN N**'xml_plan'**
    Força o otimizador de consulta a usar um plano de consulta existente para uma consulta especificada por 'xml_plan'. Para obter mais informações, consulte Especificando planos de consulta com imposição de plano. USE PLAN não pode ser especificado com instruções INSERT, UPDATE, MERGE ou DELETE.

  • TABLE HINT (exposed_object_name [ , <table_hint> [ [, ]...n ] ] )
    Aplica a dica de tabela especificada à tabela ou exibição que corresponde ao exposed_object_name. É recomendável usar uma dica de tabela como dica de consulta apenas no contexto de um guia de plano.

    exposed_object_name pode ser uma das seguintes referências:

    • Quando um alias é usado para a tabela ou exibição na cláusula FROM da consulta, exposed_object_name é o alias.

    • Quando um alias não é usado, exposed_object_name é o correspondente exato da tabela ou exibição referida na cláusula FROM. Por exemplo, se a tabela ou exibição for referida por meio de um nome de duas partes, exposed_object_name será esse mesmo nome de duas partes.

    Quando exposed_object_name é especificado sem também especificar uma dica de tabela, quaisquer índices especificados na consulta como parte de uma dica de tabela para o objeto é desconsiderado e o uso do índice é determinado pelo otimizador de consulta. Você pode usar essa técnica para eliminar o efeito de uma dica de tabela INDEX quando não puder modificar a consulta original. Consulte o exemplo J.

  • <table_hint> ::= { [ NOEXPAND ] { INDEX ( index_value [ ,...n ] ) | INDEX = ( index_value ) | FASTFIRSTROW | FORCESEEK | HOLDLOCK | NOLOCK | NOWAIT | PAGLOCK | READCOMMITTED | READCOMMITTEDLOCK | READPAST | READUNCOMMITTED | REPEATABLEREAD | ROWLOCK | SERIALIZABLE | TABLOCK | TABLOCKX | UPDLOCK | XLOCK }
    É a dica de tabela a aplicar à tabela ou exibição que corresponde ao exposed_object_name como uma dica de consulta. Para obter uma descrição dessas dicas, consulte Dicas de tabela (Transact-SQL).

    Dicas de tabela diferentes de INDEX e FORCESEEK não são permitidas como dicas de consulta, a não ser que a consulta possua uma cláusula WITH que especifique a dica de tabela. Para obter mais informações, consulte Comentários.

Comentários

Não podem ser especificadas dicas de consulta em uma instrução INSERT, exceto quando uma cláusula SELECT for usada dentro da instrução.

Só podem ser especificadas dicas de consulta na consulta de nível superior, e não em subconsultas. Quando uma dica de tabela é especificada como dica de consulta, ela pode ser especificada na consulta de nível superior ou em uma subconsulta; porém, o valor especificado para exposed_object_name na cláusula TABLE HINT deve corresponder exatamente ao nome exposto na consulta ou subconsulta.

Especificando dicas de tabela como dicas de consulta

É recomendável usar a dica de tabela INDEX ou FORCESEEK como dica de consulta apenas no contexto de um guia de plano. Guias de plano são úteis quando não é possível modificar a consulta original, por exemplo, por se tratar de um aplicativo de terceiros. A dica de consulta especificada na guia de plano é adicionada à consulta antes de ela ser compilada e otimizada. Para consultas ad hoc, use a cláusula TABLE HINT apenas ao testar instruções de guia de plano. Para todas as demais consultas ad hoc, é recomendável especificar essas dicas apenas como dicas de tabela.

Quando especificadas como uma dica de consulta, as dicas de tabela INDEX e FORCESEEK são válidas para os objetos a seguir:

  • Tabelas

  • Exibições

  • Exibições indexadas

  • Expressões de tabela comuns (a dica deve ser especificada na instrução SELECT cujo conjunto de resultados popula a expressão de tabela comum.)

  • Exibições de gerenciamento dinâmico

  • Subconsultas nomeadas

As dicas de tabela INDEX e FORCESEEK podem ser especificadas como dicas de consulta para uma consulta que não tenha dicas de tabela existentes ou podem ser usadas para substituir dicas INDEX ou FORCESEEK existentes na consulta, respectivamente. Dicas de tabela diferentes de INDEX e FORCESEEK não são permitidas como dicas de consulta, exceto se a consulta possuir uma cláusula WITH especificando a dica de tabela. Nesse caso, será necessário especificar também uma dica correspondente como dica de consulta usando TABLE HIT na cláusula OPTION para preservar a semântica da consulta. Por exemplo, se a consulta contiver a dica de tabela NOLOCK, a cláusula OPTION no parâmetro @hints do guia de plano também deverá conter a dica NOLOCK. Consulte o exemplo K. Quando uma dica de tabela diferente de INDEX ou FORCESEEK é especificada usando TABLEHINT na cláusula OPTION sem uma dica de consulta correspondente, ou vice-versa; o erro 8702 é gerado (indicando que a cláusula OPTION pode modificar a semântica da consulta) e a consulta falha. Para obter mais informações, consulte Usando as dicas de consulta INDEX e FORCESEEK em guias de plano.

Exemplos

A. Usando MERGE JOIN

O exemplo a seguir especifica que a operação JOIN na consulta é executada por MERGE JOIN.

USE AdventureWorks;
GO
SELECT * 
FROM Sales.Customer AS c
INNER JOIN Sales.CustomerAddress AS ca ON c.CustomerID = ca.CustomerID
WHERE TerritoryID = 5
OPTION (MERGE JOIN);
GO

B. Usando OPTIMIZE FOR

O exemplo a seguir instrui o otimizador de consulta a usar o valor 'Seattle' como variável local @city\_name e a usar valores estatísticos para determinar o valor da variável local @postal\_code ao otimizar a consulta.

USE AdventureWorks;
GO
DECLARE @city_name nvarchar(30);
DECLARE @postal_code nvarchar(15);
SET @city_name = 'Ascheim';
SET @postal_code = 86171;
SELECT * FROM Person.Address
WHERE City = @city_name AND PostalCode = @postal_code
OPTION ( OPTIMIZE FOR (@city_name = 'Seattle', @postal_code UNKNOWN) );
GO

C. Usando MAXRECURSION

MAXRECURSION pode ser usado para impedir que uma expressão de tabela comum recursiva mal-formada entre em loop infinito. O exemplo a seguir cria um loop infinito intencionalmente e usa a dica MAXRECURSION para limitar o número de níveis de recursão para dois.

USE AdventureWorks;
GO
--Creates an infinite loop
WITH cte (EmployeeID, ManagerID, Title) AS
(
    SELECT EmployeeID, ManagerID, Title
    FROM HumanResources.Employee
    WHERE ManagerID IS NOT NULL
  UNION ALL
    SELECT cte.EmployeeID, cte.ManagerID, cte.Title
    FROM cte 
    JOIN  HumanResources.Employee AS e 
        ON cte.ManagerID = e.EmployeeID
)
--Uses MAXRECURSION to limit the recursive levels to 2
SELECT EmployeeID, ManagerID, Title
FROM cte
OPTION (MAXRECURSION 2);
GO

Depois que o erro de codificação é corrigido, MAXRECURSION já não é necessário.

D. Usando MERGE UNION

O exemplo a seguir usa a dica de consulta MERGE UNION.

USE AdventureWorks;
GO
SELECT *
FROM HumanResources.Employee AS e1
UNION
SELECT *
FROM HumanResources.Employee AS e2
OPTION (MERGE UNION);
GO

E. Usando HASH GROUP e FAST

O exemplo a seguir usa as dicas de consulta HASH GROUP e FAST.

USE AdventureWorks;
GO
SELECT ProductID, OrderQty, SUM(LineTotal) AS Total
FROM Sales.SalesOrderDetail
WHERE UnitPrice < $5.00
GROUP BY ProductID, OrderQty
ORDER BY ProductID, OrderQty
OPTION (HASH GROUP, FAST 10);
GO

F. Usando MAXDOP

O exemplo a seguir usa a dica de consulta MAXDOP.

USE AdventureWorks ;
GO
SELECT ProductID, OrderQty, SUM(LineTotal) AS Total
FROM Sales.SalesOrderDetail
WHERE UnitPrice < $5.00
GROUP BY ProductID, OrderQty
ORDER BY ProductID, OrderQty
OPTION (MAXDOP 2);
GO

G. Usando INDEX

O exemplo a seguir usa a dica INDEX. O primeiro exemplo especifica um único índice. O segundo exemplo especifica vários índices para uma única referência de tabela. Nos dois exemplos, uma vez que a dica INDEX é aplicada em uma tabela que usa um alias, a cláusula TABLE HINT também deve especificar o mesmo alias como nome do objeto exposto.

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide1', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e 
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 2;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT(e, INDEX (IX_Employee_ManagerID)))';
GO
EXEC sp_create_plan_guide 
    @name = N'Guide2', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 2;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT(e, INDEX(PK_Employee_EmployeeID, IX_Employee_ManagerID)))';
GO

H. Usando FORCESEEK

O exemplo a seguir usa a dica de tabela FORCESEEK. Como a dica INDEX é aplicada em uma tabela que usa um nome de duas partes, a cláusula TABLE HINT também deve especificar o mesmo nome de duas partes como nome do objeto exposto.

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide3', 
    @stmt = N'SELECT c.LastName, c.FirstName, HumanResources.Employee.Title
              FROM HumanResources.Employee
              JOIN Person.Contact AS c ON HumanResources.Employee.ContactID = c.ContactID
              WHERE HumanResources.Employee.ManagerID = 3
              ORDER BY c.LastName, c.FirstName;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT( HumanResources.Employee, FORCESEEK))';
GO

I. Usando várias dicas de tabela

O exemplo a seguir aplica a dica INDEX a uma tabela e a dica FORCESEEK a outra.

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide4', 
    @stmt = N'SELECT e.ManagerID, c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e 
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 3;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT ( e, INDEX( IX_Employee_ManagerID ) ) 
                       , TABLE HINT ( c, FORCESEEK) )';
GO

J. Usando TABLE HINT para substituir uma dica de tabela existente

O exemplo a seguir mostra como usar a dica TABLE HINT sem especificar uma dica para substituir o comportamento da dica de tabela INDEX especificado na cláusula de consulta FROM.

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide5', 
    @stmt = N'SELECT e.ManagerID, c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e WITH (INDEX (IX_Employee_ManagerID))
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 3;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT(e))';
GO

K. Especificando dicas de tabela que afetam a semântica

O exemplo a seguir contém duas dicas de tabela na consulta: NOLOCK, que afeta a semântica, e INDEX, que não afeta a semântica. Para preservar a semântica da consulta, a dica NOLOCK é especificada na cláusula OPTIONS do guia de plano. Além da dica NOLOCK, as dicas INDEX e FORCESEEK são especificadas e substituem a dica INDEX, que não afeta a semântica, na consulta, quando a instrução é compilada e otimizada.

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide6', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e 
                   WITH (NOLOCK, INDEX (PK_Employee_EmployeeID))
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 3;',
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT ( e, INDEX( IX_Employee_ManagerID) , NOLOCK, FORCESEEK ))';
GO

O exemplo a seguir mostra um método alternativo para preservar a semântica da consulta e permitir que o otimizador escolha um índice diferente do índice especificado na dica de tabela. Isso é feito especificando-se a dica NOLOCKna cláusula OPTIONS (porque afeta a semântica) e a palavra-chave TABLE HINT com apenas uma referência de tabela e nenhuma dica INDEX.

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide7', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e 
                   WITH (NOLOCK, INDEX (PK_Employee_EmployeeID))
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 2;',
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT ( e, NOLOCK))';
GO