Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Por que o Query Optimizer ignora totalmente os índices de exibição indexados?


tl;dr resposta:Se você não especificar NOEXPAND, o otimizador de consulta não tem ideia de que você está enviando uma seleção simples de uma visualização. Teria que corresponder à expansão de sua consulta (que é tudo o que vê) com algum índice de exibição. Provavelmente não se incomodará quando for uma junção de cinco vias com um monte de elencos.

A correspondência do índice de exibição com uma consulta é um problema difícil, e acredito que sua exibição seja muito complicada para o mecanismo de consulta corresponder a um índice. Considere esta uma de suas dúvidas:
SELECT ID, Code1 FROM EntityView Where Code1 > 'NR%';

É óbvio para você que isso pode usar um índice de exibição, mas essa não é a consulta que o mecanismo de consulta vê. As visualizações são expandidas automaticamente se você não especificar NOEXPAND, então é isso que vai para o mecanismo de consulta:
SELECT ID, Code1 FROM (
    SELECT e.ID, 'NR'+CAST(c1.CODE as nvarchar(11)) as Code1, 'NR'+CAST(c2.CODE as nvarchar(11)) as Code2, 'NR'+CAST(c3.CODE as nvarchar(11)) as Code3, 'NR'+CAST(c4.CODE as nvarchar(11)) as Code4, 'NR'+CAST(c5.CODE as nvarchar(11)) as Code5
    FROM dbo.Entity e
        inner join  dbo.Classificator1 c1 on e.ID = c1.ID
        inner join  dbo.Classificator2 c2 on e.ID = c2.ID
        inner join  dbo.Classificator3 c3 on e.ID = c3.ID
        inner join  dbo.Classificator4 c4 on e.ID = c4.ID
        inner join  dbo.Classificator5 c5 on e.ID = c5.ID;
) AS V;

O mecanismo de consulta vê essa consulta complicada e possui informações (mas provavelmente não SQL de definições de exibição) que descrevem os índices de exibição que foram definidos. Dado que essa consulta e os índices de exibição têm várias junções e conversões, a correspondência é um trabalho árduo.

Lembre-se de que você sabe que as junções e correspondências são idênticas nesta consulta e nos índices de exibição, mas o processador da consulta não sabe disso. Ele trata esta consulta da mesma forma como se ela juntasse cinco cópias do Classificator3, ou se uma das colunas fosse 'NQ'+CAST(c2.CODE as varchar(12)). O correspondente de índice de exibição (supondo que tenha feito qualquer tentativa de corresponder a essa consulta complicada) teria que corresponder todos os detalhes dessa consulta aos detalhes dos índices de exibição nas tabelas envolvidas.

O mecanismo de consulta tem como objetivo nº 1 descobrir uma maneira de executar a consulta com eficiência. Provavelmente, ele não foi projetado para gastar muito tempo tentando corresponder todos os detalhes de uma junção de cinco vias e CASTs a um índice de exibição.

Se eu tivesse que adivinhar, suspeito que o matcher de índice de exibição veja que as colunas de resultado da consulta não são nem mesmo colunas de qualquer tabela subjacente (por causa do CAST) e simplesmente não se incomoda em tentar nada. Adicionado :Estou errado. Acabei de tentar a sugestão de Martin de atualizar as estatísticas para tornar a consulta cara, e um índice de exibição foi correspondido para algumas dessas consultas sem NOEXPAND. O view matcher é mais inteligente do que eu pensava! Portanto, o problema é que o correspondente de visualização provavelmente se esforçará mais para corresponder a uma consulta complicada se seu custo for muito alto.

Use a dica NOEXPAND em vez de esperar que o mecanismo de consulta seja capaz de descobrir o que corresponde aqui. NOEXPAND é absolutamente seu amigo, porque então o mecanismo de consulta consegue ver
SELECT ID, Code1 FROM EntityView Where Code1 > 'NR%';

e é imediatamente óbvio para o matcher do índice de exibição que existe um índice útil.

(Observação:seu código SQL Fiddle tem todas as 5 referências de chave estrangeira para a mesma tabela, o que provavelmente não é o que você deseja.)