Por que o SQL Server não possui nenhuma solicitação de índice ausente nos DMVs ou nos planos de consulta?

14

Eu tenho um banco de dados do SQL Server em que as consultas são muito lentas e há muitos bloqueios e bloqueios.

Quando olho para os DMVs de índice ausentes e os planos de consulta, não há sugestões.

Por que é que?

Erik Darling
fonte

Respostas:

17

Há muitas razões pelas quais você pode não ter solicitações de índice ausentes!

Examinaremos alguns dos motivos com mais detalhes e também falaremos sobre algumas das limitações gerais do recurso.

Limitações gerais

Primeiro, de: Limitações do recurso de índices ausentes :

  • Ele não especifica uma ordem para as colunas serem usadas em um índice.

Conforme observado nestas perguntas e respostas: Como o SQL Server determina a ordem das colunas principais nas solicitações de índice ausentes? , a ordem das colunas na definição de índice é ditada pelo predicado Igualdade vs Desigualdade e depois pela posição ordinal da coluna na tabela.

Não há suposições sobre a seletividade e pode haver uma ordem melhor disponível. É seu trabalho descobrir isso.

Índices Especiais

As solicitações de índice ausentes também não cobrem índices 'especiais', como:

  • Agrupado
  • Filtrado
  • Particionado
  • Comprimido
  • XML-ed
  • Spatial-ed
  • Columnstore-d
  • Visualização indexada

Quais colunas são consideradas?

As colunas-chave do Índice ausente são geradas a partir de colunas usadas para filtrar resultados, como aqueles em:

  • JOINs
  • Cláusula WHERE

As colunas incluídas no índice ausente são geradas a partir de colunas exigidas pela consulta, como as de:

  • SELECT
  • GRUPO POR
  • ORDENAR POR

Mesmo que com bastante frequência, as colunas pelas quais você está ordenando ou agrupando podem ser benéficas como colunas-chave. Isso remonta a uma das limitações:

  • Não se destina a ajustar uma configuração de indexação.

Por exemplo, esta consulta não registrará uma solicitação de índice ausente, mesmo que a adição de um índice em LastAccessDate impeça a necessidade de Classificar (e espalhar para o disco).

SELECT TOP (1000) u.DisplayName
FROM dbo.Users AS u
ORDER BY u.LastAccessDate DESC;

NUTS

Este agrupamento também não consulta no local.

SELECT TOP (20000) u.Location
FROM dbo.Users AS u
GROUP BY u.Location

NUTS

Isso não parece muito útil!

Bem, sim, mas é melhor que nada. Pense na falta de pedidos de índice como um bebê chorando. Você sabe que há um problema, mas depende de você, como adulto, descobrir qual é esse problema.

Você ainda não me disse por que eu não os tenho, embora ...

Relaxe, bucko. Estamos chegando lá.

Sinalizadores de rastreamento

Se você ativar o TF 2330 , as solicitações de índice ausentes não serão registradas. Para descobrir se você tem isso ativado, execute o seguinte:

DBCC TRACESTATUS;

Reconstruções de índice

A reconstrução de índices limpará as solicitações de índice ausentes. Portanto, antes de começar o Hi-Ho-Silver-Away, reconstruindo todos os índices no segundo em que um pingo de fragmentação se infiltra, pense nas informações que você está limpando toda vez que faz isso.

Você também pode pensar em Por que desfragmentar seus índices não está ajudando , de qualquer maneira. A menos que você esteja usando o Columnstore .

Adicionando, removendo ou desativando índices

Adicionar, remover ou desativar um índice limpará todas as solicitações de índice ausentes para essa tabela. Se você estiver trabalhando com várias alterações de índice na mesma tabela, certifique-se de escrevê-las todas antes de fazer alguma.

Planos triviais

Se um plano for simples o suficiente, e a opção de acesso ao índice for óbvia o suficiente, e o custo for baixo o suficiente, você obterá um plano trivial.

Isso significa efetivamente que não houve decisões baseadas em custos para o otimizador tomar.

Via Paul White :

Os detalhes de quais tipos de consulta podem se beneficiar do Trivial Plan mudam com frequência, mas coisas como junções, subconsultas e predicados de desigualdade geralmente impedem essa otimização.

Quando um plano é trivial, as fases adicionais de otimização não são exploradas e os índices ausentes não são solicitados .

Veja a diferença entre essas consultas e seus planos :

SELECT *
FROM dbo.Users AS u
WHERE u.Reputation = 2;

SELECT *
FROM dbo.Users AS u
WHERE u.Reputation = 2
AND 1 = (SELECT 1);

NUTS

O primeiro plano é trivial e nenhuma solicitação é mostrada. Pode haver casos em que os erros impedem a exibição de índices ausentes nos planos de consulta; eles geralmente são registrados com mais confiabilidade nas DMVs de índice ausentes.

SARGability

Predicados em que o otimizador não seria capaz de usar um índice com eficiência, mesmo com um índice, podem impedir que eles sejam registrados.

Coisas que geralmente não são SARGable são:

  • Colunas agrupadas em funções
  • Column + SomeValue = SomePredicate
  • Column + AnotherColumn = SomePredicate
  • Coluna = @Variable OU @Variable IS NULL

Exemplos:

SELECT *
FROM dbo.Users AS u
WHERE ISNULL(u.Age, 1000) > 1000;


SELECT *
FROM dbo.Users AS u
WHERE DATEDIFF(DAY, u.CreationDate, u.LastAccessDate) > 5000


SELECT *
FROM dbo.Users AS u
WHERE u.UpVotes + u.DownVotes > 10000000


DECLARE @ThisWillHappenWithStoredProcedureParametersToo NVARCHAR(40) = N'Eggs McLaren'
SELECT *
FROM dbo.Users AS u
WHERE u.DisplayName LIKE @ThisWillHappenWithStoredProcedureParametersToo 
      OR @ThisWillHappenWithStoredProcedureParametersToo IS NULL;

Nenhuma dessas consultas registrará solicitações de índice ausentes. Para mais informações, consulte os seguintes links:

Você já tem um índice correto

Veja este índice:

CREATE INDEX ix_whatever ON dbo.Posts(CreationDate, Score) INCLUDE(OwnerUserId);

Parece bom para esta consulta:

SELECT p.OwnerUserId, p.Score
FROM dbo.Posts AS p
WHERE p.CreationDate >= '20070101'
AND   p.CreationDate < '20181231'
AND   p.Score >= 25000
AND 1 = (SELECT 1)
ORDER BY p.Score DESC;

O plano é uma busca simples ...

NUTS

Mas como a coluna principal é para o predicado menos seletivo, acabamos fazendo mais trabalho do que deveríamos:

Tabela 'Posts'. Contagem de escaneamentos 13, leituras lógicas 136890

Se alterarmos a ordem da coluna da chave de índice, faremos muito menos trabalho:

CREATE INDEX ix_whatever ON dbo.Posts(Score, CreationDate) INCLUDE(OwnerUserId);

NUTS

E significativamente menos leituras:

Tabela 'Posts'. Contagem de digitalizações 1, leituras lógicas 5

O SQL Server está criando índices para você

Em certos casos, o SQL Server optará por criar um índice em tempo real por meio de um spool de índice. Quando um spool de índice está presente, uma solicitação de índice ausente não será. Certamente, adicionar o índice você mesmo pode ser uma boa ideia, mas não conte com o SQL Server para ajudá-lo a descobrir isso.

NUTS

Erik Darling
fonte