Usando a dica de tabela FORCESEEK

A dica de tabela FORCESEEK força o otimizador de consulta a usar só uma operação de busca de índice como o caminho de acesso para os dados na tabela ou exibição referenciada na consulta. Você pode usar essa dica de tabela para substituir o plano padrão escolhido pelo otimizador de consulta para evitar problemas de desempenho causados por um plano de consulta ineficiente. Por exemplo, se um plano contiver operadores de verificação de tabela ou de índice, e as tabelas correspondentes criarem um número alto de leituras durante a execução da consulta, como observado na saída STATISTICS IO, forçar uma operação de índice de busca poderia resultar em um desempenho melhor da consulta. Isso é especialmente verdadeiro quando a cardinalidade ou as estimativas de custo incorretas fizerem o otimizador favorecer operações de verificação em tempo compilação de plano.

FORCESEEK aplica-se a ambas às operações de busca de índice clusterizado e não-clusterizado . Pode ser especificada para qualquer tabela ou exibição na cláusula FROM de uma instrução SELECT e na cláusula FROM <table_source> de uma instrução UPDATE ou DELETE .

Observação sobre cuidadosCuidado

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

Avaliando planos de consulta para aplicabilidade de FORCESEEK

A dica de tabela FORCESEEK pode ser útil quando o plano de consulta usa um operador de tabela ou de verificação de índice em uma tabela ou exibição, mas um operador de busca de índice pode ser mais eficiente. Considere a consulta seguinte e o plano de execução subseqüente.

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

O seguinte plano de execução mostra que o otimizador de consulta escolheu um operador de verificação de índice clusterizado para acessar os dados em ambas as tabelas.

Plano de execução com operadores Clustered Index Scan

Você pode forçar o otimizador de consulta a executar uma operação de busca na tabela Sales.SalesOrderDetail especificando a dica FORCESEEK como mostrado na consulta seguinte.

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

O plano de execução seguinte mostra os resultados de usar a dica de FORCESEEK na consulta. Uma operação de busca de índice clusterizado é usada para acessar os dados na tabela Sales.SalesOrderDetail.

Plano de execução com operadores Clustered Index Seek

União de índice e suporte de interseção

A dica de FORCESEEK aceita uniões de índice e interseções. A dica faz o otimizador de consulta usar estas técnicas com maior probabilidade. Para evitar reduzir a velocidade o tempo de compilação de consultas simples, uniões de índice e interseções são normalmente escolhidas só de acordo com regras que levam em conta a cardinalidade e a seletividade das colunas. Porém, quando a dica de FORCESEEK é especificada, são ignoradas tais regras e estas técnicas sempre são consideradas. Por exemplo, considere a consulta abaixo:

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

Se houver índices separados, não clusterizado em colunas a e b na tabela T, um plano de interseção de índice pode ser escolhido. Quer dizer, o plano contém uma operação de busca de índice não-clusterizado na coluna a e uma operação de busca de índice não-clusterizado na coluna b e intersecta os conjuntos chave de índice resultantes antes de executar uma operação de procura na tabela base.

No exemplo seguinte, um plano de união de índice é escolhido. Quer dizer, o plano contém uma operação de busca na coluna a e uma operação de busca na coluna b e une os conjuntos chave de índice resultantes, antes de executar uma operação de procura na tabela base.

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

Usando FORCESEEK em consultas que usam LIKE ou IN

O otimizador de consultas e a estimativa precária de cardinalidade também podem fazer o otimizador executar uma tabela ou operação de verificação de índice em lugar de uma busca de índice quando uma consulta usar IN ou LIKE como predicados de pesquisa.

O exemplo a seguir demonstra como a dica de FORCESEEK pode forçar o otimizador de consulta a executar uma operação de busca de índice no lugar de uma verificação de tabela quando LIKE ou IN são usados como predicados de pesquisa. Para exibir os planos de execução de consulta, clique no botão da barra de ferramentas Incluir Plano de Execução Real antes de executar o exemplo.

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

Usando FORCESEEK em exibições

FORCESEEK pode ser especificada com ou sem uma dica de índice. Quando você aplicar uma dica de tabela FORCESEEK a uma exibição ou exibição indexada, a dica FORCESEEK é propagada recursivamente por todas as tabelas na versão expandida da exibição. A dica de índice, se especificada, é ignorada. Se as tabelas subjacentes não tiverem pelo menos um índice cada, nenhum plano será encontrado e o erro 8622 é retornado.

Quando você usa as dicas FORCESEEK e NOEXPAND juntas em uma referência a uma exibição indexada, a exibição indexada é usada sem se expandir primeiro. A dica FORCESEEK é diretamente aplicada à exibição indexada tratada apenas como uma tabela.

Se você aplicar uma dica FORCESEEK a uma referência de tabela, a referência de tabela não poderá participar na correspondência de exibição indexada. Entretanto, outras partes da consulta que são não afetadas pela dica de FORCESEEK podem participar na correspondência de exibição indexada. Isso é comparável ao comportamento da correspondência de exibição indexada, quando usada com dicas de INDEX.

Considerações sobre as práticas recomendadas

Recomendamos as seguinte práticas:

  • Antes de usar a dica de tabela FORCESEEK, verifique se as estatísticas no banco de dados são atuais e precisas.

    Estatísticas atualizadas permitem que o otimizador avalie com precisão o custo de planos de consultas diferentes e escolha um plano de alta qualidade. Por isso, recomendamos definir o AUTO_CREATE_STATISTICS e AUTO_UPDATE_STATISTICS como ON (o padrão) para cada banco de dados de usuário. Alternativamente, você pode atualizar as estatísticas manualmente em uma tabela ou exibição usando a instrução UPDATE STATISTICS.

  • Avalie a consulta para itens que podem causar cardinalidade ou estimativas de custo precárias e remova esses itens, se possível. Por exemplo, substitua variáveis locais com parâmetros ou literais e limite o uso de funções com valor de tabela com várias instruções e variáveis de tabela na consulta. Para obter mais informações sobre outros itens a procurar, consulte Statistics Used by the Query Optimizer in Microsoft SQL Server 2005.

  • Não use a dica INDEX desnecessariamente em combinação com FORCESEEK. Quer dizer, se FORCESEEK produz apenas um plano suficiente, usar também a dica INDEX pode limitar excessivamente as escolhas que o otimizador tem. Além disso, uma dica INDEX fará com que a sua consulta falhe se você alterar o esquema físico de sua tabela para eliminar o índice especificado na dica. Em contraste, desde que, exista pelo menos um índice utilizável na tabela na qual a dica FORCESEEK é aplicada, a consulta compilará até mesmo quando você alterar suas estruturas de índice.

  • Não use a dica INDEX INDEX (0) com a dica FORCESEEK. INDEX (0) força uma verificação da tabela base. Quando usada com FORCESEEK, nenhum plano é encontrado e o erro 8622 é retornado.

  • Não use a dica de consulta USE PLAN com a dica FORCESEEK. Se você o fizer, a dica FORCESEEK será ignorada.