SQL Server execução da consulta plano mostra errado “contagem de linhas real” em um índice e desempenho utilizado é terrível lenta

StackOverflow https://stackoverflow.com/questions/225309

Pergunta

Hoje me deparei com um problema de desempenho interessante com um procedimento armazenado em execução no Sql Server 2005 SP2 em um db em execução no nível compatível de 80 (SQL2000).

Os proc corre cerca de 8 minutos e os shows plano de execução o uso de um índice com uma contagem de linhas real de 1.339.241.423 que é de cerca fator 1.000 maior do que o número de linhas real "real" da própria tabela, que é 1.144.640 como mostrado corretamente pelo número de linhas estimado. Portanto, a contagem de linhas real dado pelo otimizador de plano de consulta é Sem dúvida! Errado

text alt

Curiosamente, quando eu copiar os procs parâmetro valores dentro do proc a variáveis ??locais e de usar as variáveis ??locais na consulta real, tudo funciona bem - o proc corre 18 segundos e os shows plano de execução a contagem de linhas real direita.

EDIT: Como sugerido por TrickyNixon, este parece ser um sinal do problema parâmetro sniffing. Mas, na verdade, eu recebo em ambos os casos exatamente o mesmo plano de execução. índices mesmos são beeing usado na mesma ordem. A única diferença que eu vejo é o caminho para a alta contagem de linhas real sobre o índice PK_ED_Transitions quando se utiliza diretamente os ParameterValues.

Eu fiz dbreindex dbcc e UPDATE estatísticas já sem qualquer sucesso. SHOW_STATISTICS DBCC mostra bons dados para o índice, também.

O proc é criado com RECOMPILE assim que cada vez que é executado um novo plano de execução está sendo compilado.

Para ser mais específico - este corre rápido:

CREATE  Proc [dbo].[myProc](
@Param datetime
)
WITH RECOMPILE 
as

set nocount on

declare @local datetime
set @local = @Param

select 
some columns
from 
table1
where
column = @local
group by
some other columns

e esta versão corre terrivelmente lento, mas produz exatamente o mesmo plano de execução (além do muito alta contagem de linhas real sobre um índice utilizado):

CREATE  Proc [dbo].[myProc](
@Param datetime
)
WITH RECOMPILE 
as

set nocount on

select 
some columns
from 
table1
where
column = @Param
group by
some other columns

Todas as idéias? Alguém lá fora, quem sabe onde o SQL Server obtém o valor de contagem de linhas real a partir do cálculo planos de consulta?

Atualizar : Eu tentei a consulta em outro woth servidor COPAT set modo a 90 (SQL2005). É o mesmo comportamento. Eu acho que vai abrir uma chamada de apoio da senhora, porque isto me parece um erro.

Foi útil?

Solução

Ok, finalmente eu tenho para ele próprio.

Os dois planos de consulta são diferentes em um pequeno detalhe que eu perdi na primeira. o lento usa um operador de loops aninhados para juntar duas subconsultas juntos. E que resulta em elevado número na contagem de linha atual do operador verificação de índice que é simplesmente o resultado de multiplicadas pelo número de linhas de entrada um com número de linhas de entrada b.

Eu ainda não sei por que o otimizador decide usar os loops aninhados em vez de um jogo de hash que corre 1.000 temporizador mais rápida neste caso, mas eu poderia lidar com o meu problema criando um novo índice, para que o motor faz um busca de índice statt em vez de uma varredura de índice sob os laços aninhados.

Outras dicas

Quando você está verificando planos de execução do proc armazenados contra o copiar / colar consulta, você está usando os planos estimadas ou os planos reais? Certifique-se de clique em Consultar, Incluir Plano de Execução, e depois executar cada consulta. Compare esses planos e ver quais são as diferenças.

Parece ser um caso de Parâmetro Sniffing. Aqui está uma excelente explicação, juntamente com possíveis soluções: Eu cheiro um parâmetro!

Aqui está outro segmento StackOverflow que os endereços que: Parâmetro Sniffing (ou falsificação) em SQL Server

Para mim, isso ainda soa como se as estatísticas estão incorretos. Reconstruir os índices não necessariamente atualizá-los.

Você já experimentou um UPDATE STATISTICS explícita para as tabelas afetadas?

Você executar sp_spaceused para verificar se o SQL Server está com o resumo certa para que a tabela? Eu acredito em SQL 2000 o motor costumava usar esse tipo de metadados quando a construção de planos de execução. Estamos habituados a ter de correr DBCC UPDATEUSAGE semanal para atualizar os metadados em alguns dos quadros que mudam rapidamente, como SQL Server estava escolhendo os índices erradas devido aos dados de contagem de linha incorreta.

Você está executando o SQL 2005 e BOL diz que em 2005 você não deve ter para executar UPDATEUSAGE mais, mas já que você está no modo compat 2000 você pode achar que ele ainda é necessária.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top