Eu tenho uma consulta baseada em duas tabelas recém-criadas em SQL Server 2005
. Eu criei um índice nessas tabelas. Mas quando escrevo uma consulta com JOIN
condição, o número de linhas reais retornadas é muito alto, enquanto o número estimado de linhas é menor. E o plano de consulta usa um loop aninhado. [O diagrama do plano de consulta é fornecido abaixo.] Como essas são novas tabelas, acho que as estatísticas obsoletas usuais não são o motivo aqui.
Posso reescrever esta consulta usando NOT EXISTS
(conforme mostrado na Consulta 2) e o número real de linhas é reduzido. Mas tenho outros requisitos para buscar detalhes da tabela LWTest usando INNER JOIN
- o alto número de linhas reais é um problema.
Portanto, alguma pista de por que o número real de linhas é tão alto, embora haja índice e estatísticas? O que pode ser feito para derrubá-lo?
Nota: Número de linhas em TransmittedManifests –904. Número de linhas no LWTest -- 829785
ATUALIZAR
Observação2: Compatibility_Level é 90. O tempo decorrido para a Consulta 1 é 64 ms. O tempo decorrido da consulta 2 é de 6 ms.
Nota3: Tentei OPTION (RECOMPILE), reconstruir índice e ATUALIZAR ESTATÍSTICAS COM FULLSCAN nestas duas tabelas. Mas o número real de linhas ainda é alto.
Agradecimentos a Martin Smith pelos detalhes da diferença na contagem por execução (estimativa) e contagem total (real). As linhas reais são contadas em todas as execuções, as estimadas são contadas por execução. Linhas estimadas, linhas reais e contagem de execuções .
Para a Consulta 1, o ActualExecutions
="904" para a tabela LWTest.
Consulta
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
SET STATISTICS IO ON
PRINT 'BEGIN -----------------------------------------'
--Query 1
SELECT T.[Manifest]
FROM dbo.TransmittedManifests T
LEFT OUTER JOIN dbo.LWTest LW (NOLOCK)
ON LW.Manifest = T.Manifest
WHERE LW.Manifest IS NULL
PRINT 'QUERY 1 COMPLETED -----------------------------------------'
--Query 2
SELECT T.[Manifest]
FROM dbo.TransmittedManifests T
WHERE NOT EXISTS (SELECT Manifest FROM dbo.LWTest L
WHERE L.Manifest = T.Manifest
)
PRINT 'QUERY 2 COMPLETED -----------------------------------------'
--Query 3
SELECT T.[Manifest],LineItemID,InvoicedQuantity
FROM dbo.TransmittedManifests T
INNER JOIN dbo.LWTest LW (NOLOCK)
ON LW.Manifest = T.Manifest
Esquema de tabela
Plano de consulta 2
O número de registros na tabela TransmittedManifests é muito menor que o número de registros em LWTest. Nesse cenário, uma boa solução é usar a
NOT EXISTS
abordagem (como na Consulta 2) para reduzir o número de linhas reais. Refer Joins sem JOIN - Rob FarleyAgora, o comentário de Martin Smith me ajudou a desmistificar a contagem por execução (estimativa) e contagem total (real). Para a Consulta 1, o
ActualExecutions
="904" para a tabela LWTest. Portanto, 128385/904 = 142 são as linhas reais por execução, que estão um pouco próximas da estimativa de 104.No SQL Server 2005, o
ActualExecutions
pode ser visto fazendo um rastreamento do criador de perfil adicionandoperformance
eventos conforme mostrado no diagrama abaixo. [No SQL Server 2012, pude ver essas informações capturadas no próprio diagrama do plano de execução].XML
Configurações de rastreamento do SQL Server 2005