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:
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:
fonte
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.Respostas:
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 doLEFT JOIN ... IS NOT NULL
. O otimizador já o removeu (os planos "deixaram semi-junções" na JOIN final), mas eu usaria EXISTS para maior clarezaAlgo como:
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
fonte