OPTION FORCE ORDER melhora o desempenho até que as linhas sejam excluídas

9

Eu tenho uma consulta um pouco complexa do SQL Server 2008 (cerca de 200 linhas de SQL bastante densa) que não estava funcionando conforme eu precisava. Com o tempo, o desempenho caiu de cerca de 0,5 segundos para cerca de 2 segundos.

Observando o plano de execução, era bastante óbvio que, ao reordenar as junções, o desempenho poderia ser melhorado. Eu fiz, e foi ... até cerca de 0,3 segundos. Agora a consulta tem a dica "OPTION FORCE ORDER" e a vida é boa.

Hoje vem-me hoje, limpando o banco de dados. Eu arquivo cerca de 20% das linhas, não realizando nenhuma ação no banco de dados relevante, exceto excluindo linhas ... o plano de execução é TOTALMENTE processado . Ele julga completamente quantas linhas determinadas subárvores retornarão e (por exemplo) substitui um:

<Hash>

com

<NestedLoops Optimized='false' WithUnorderedPrefetch='true'>

Agora, o tempo de consulta aumenta de cerca de 0,3s para cerca de 18s. (!) Só porque apaguei linhas. Se eu remover a dica de consulta, voltarei ao tempo de consulta de cerca de 2s. Melhor, mas pior.

Reproduzi o problema depois de restaurar o banco de dados em vários locais e servidores. Simplesmente excluir cerca de 20% das linhas de cada tabela sempre causa esse problema.

  1. É normal que uma ordem de junção forçada faça com que as estimativas da consulta sejam completamente imprecisas (e, portanto, imprevisíveis no tempo da consulta)?
  2. Devo apenas esperar que eu tenha que aceitar um desempenho de consulta abaixo do ideal ou assisti-lo como um falcão e editar manualmente as dicas de consulta? Ou talvez também indique todas as junções? .3s a 2s é um grande sucesso.
  3. É óbvio por que o otimizador explodiu após a exclusão de linhas? Por exemplo, "sim, foi necessária uma varredura de amostra e, como arquivei a maioria das linhas anteriormente no histórico de dados, a amostra produziu resultados esparsos e subestimou a necessidade de uma operação de hash classificada"?

Se você deseja ver os planos de execução, sugira um local para publicá-los. Caso contrário, eu experimentei a parte mais impressionante. Aqui está a estimativa incorreta fundamental, os números em parênteses são (estimados: reais) linhas.

                             /  Clustered Index Scan (908:7229)
Nested Loops (Inner Join) --<
                             \  NonClustered Index Seek (1:7229)

Observe que o loop interno deve verificar 908 linhas, mas verifica 52.258.441. Se fosse preciso, esse ramo teria cerca de 2 ms, em vez de 12 segundos. Antes de excluir as linhas, essa estimativa de junção interna era desativada apenas por um fator total de 2 e era executada como uma correspondência de hash em dois índices em cluster.

Shannon
fonte

Respostas:

6

É normal que uma ordem de junção forçada faça com que as estimativas da consulta sejam completamente imprecisas (e, portanto, imprevisíveis no tempo da consulta)?

O uso do FORCE ORDER não está tornando as estimativas imprecisas, a exclusão de linhas fez. Forçar uma atualização de estatísticas na tabela pode melhorar a precisão da estimativa.

Devo apenas esperar que eu tenha que aceitar um desempenho de consulta abaixo do ideal ou assisti-lo como um falcão e editar manualmente as dicas de consulta? Ou talvez também indique todas as junções? .3s a 2s é um grande sucesso.

É preferível garantir que o otimizador receba as informações necessárias para gerar o melhor plano, sem usar a dica FORCE ORDER. Ao fazer isso, ele deve lidar melhor com as alterações na distribuição de dados subjacente sem exigir intervenção manual. Dito isto, se a natureza dos dados for tal que a cardinalidade possa variar significativamente de hora em hora ou dia a hora, considere usar um guia de plano para garantir que o plano seja fixo.

É óbvio por que o otimizador explodiu depois de excluir linhas? Por exemplo, "sim, foi necessária uma varredura de amostra e, como arquivei a maioria das linhas anteriormente no histórico de dados, a amostra produziu resultados esparsos e subestimou a necessidade de uma operação de hash classificada"?

Você não mencionou a contagem de linhas nas tabelas de problemas, mas é provável que as exclusões:

  • não removeu linhas suficientes para acionar uma atualização de estatísticas. Isso deve ocorrer quando 20% das linhas foram modificadas, mas existe a opção de usar o sinalizador de rastreamento 2371 para ativar um limite dinâmico.
  • acionou uma atualização de estatísticas, mas a amostra coletada não era representativa. Corrija isso executando uma atualização manual do WITH FULLSCAN .

Você também pode encontrar bons problemas de detecção de parâmetros à moda antiga , para os quais existem inúmeras opções para contornar. WITH RECOMPILE pode ser uma opção cara para especificar com uma consulta desse tamanho, mas vale a pena investigar no nível do procedimento e da instrução.

Mark Storey-Smith
fonte
Apenas um esclarecimento, provavelmente é semântica: "O uso do FORCE ORDER não está tornando as estimativas imprecisas, a exclusão de linhas sim." Então você acha que é apenas uma chance aleatória que a remoção do "FORCE ORDER" melhorou tanto a consulta? A dica não fez com que o otimizador confiasse nas estatísticas nas quais ele preferiria enfatizar menos ou não foi descoberto no teste do aplicativo porque essa estatística menos confiável raramente era essencial.
Shannon
Acho que sim, já que a escolha preferida dos planejadores pelos otimizadores lida com as estatísticas imprecisas, mas o plano que resultou da ordem de junção sendo forçada não. Não estou ciente de que o FORCE ORDER está causando alguma alteração na avaliação das estatísticas; outra pessoa entrará em contato se souber alguma coisa em contrário. Também é necessário considerar se o valor que você escolheu para OTIMIZAR PARA é apropriado. Pode ser que as estatísticas estejam absolutamente boas, mas você está forçando um plano com base em um valor que não é representativo.
Mark-Storey-Smith
Direita. Tenho o mesmo problema de desempenho ao passar os parâmetros exatamente como os otimizei. Obrigado novamente.
Shannon