Por que o número de execuções de varredura de índice em cluster é tão alto?

15

Tenho duas consultas semelhantes que geram o mesmo plano de consulta, exceto que um plano de consulta executa uma Verificação de Índice em Cluster 1316 vezes, enquanto o outro executa uma vez.

A única diferença entre as duas consultas é um critério de data diferente. A consulta de longa duração, na verdade, restringe os critérios de data e retira menos dados.

Eu identifiquei alguns índices que ajudarão nas duas consultas, mas só quero entender por que o operador Clustered Index Scan está executando 1316 vezes em uma consulta que é praticamente a mesma daquela em que é executada 1 vez.

Eu verifiquei as estatísticas do PK que está sendo verificado e estão relativamente atualizadas.

Consulta original:

select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
    select incident_id as exported_incident_id
    from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-06-01 00:00:00.000' and '2011-07-01 00:00:00.000'
    and exported_incidents.exported_incident_id is not null

Gera este plano: insira a descrição da imagem aqui

Depois de restringir os critérios do período:

select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
    select incident_id as exported_incident_id
    from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'
    and exported_incidents.exported_incident_id is not null

Gera este plano: insira a descrição da imagem aqui

Seibar
fonte
Você pode copiar / colar suas consultas em um bloco de código em vez de arquivos de imagem?
Eric Humphrey - lotsahelp
Claro - adicionei as consultas que estão gerando cada plano.
Seibar 06/12/19
Em qual tabela a verificação de índice em cluster está ocorrendo?
Eric Humphrey - lotsahelp
A varredura de índice clusterizado está na subconsulta na junção esquerda (PostNFIRSSummary)
Seibar
11
Presumivelmente, na última vez em que as estatísticas foram atualizadas, havia apenas zero ou uma linha atendendo aos FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'critérios e, desde então, houve um número desproporcional de inserções nesse intervalo. Ele estima que apenas 1,07 execuções serão necessárias para esse período. Não são os 1.316 que se seguem na realidade.
Martin Smith

Respostas:

9

O JOIN após a verificação fornece uma pista: com menos linhas em um lado da última junção (lendo da direita para a esquerda, é claro), o otimizador escolhe um "loop aninhado" e não uma "junção de hash".

No entanto, antes de analisar isso, pretendo eliminar a pesquisa de chave e o DISTINCT.

  • Pesquisa principal: seu índice em FIR_Incident deve estar cobrindo, provavelmente (FI_IncidentDate, incidentid)ou o contrário. Ou tenha ambos e veja qual é usado com mais frequência (ambos podem ser)

  • O DISTINCTé uma conseqüência do LEFT JOIN ... IS NOT NULL. O otimizador já o removeu (os planos "deixaram semi-junções" na JOIN final), mas eu usaria EXISTS para maior clareza

Algo como:

select 
    F.IncidentID
from 
    FIR_Incident F
where 
    exists (SELECT * FROM postnfirssummary P
           WHERE P.incident_id = F.incidentid)
    AND
    F.FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'

Você também pode usar guias de plano e dicas de JOIN para fazer o SQL Server usar uma junção de hash, mas tente fazê-lo funcionar normalmente primeiro: um guia ou uma dica provavelmente não resistirá ao teste do tempo, porque são úteis apenas para os dados e consultas que você executa agora, não no futuro

gbn
fonte