Database
 sql >> Base de Dados >  >> RDS >> Database

Perguntas e respostas da nossa série de webinars Parameter Sniffing


Nas últimas duas quartas-feiras, realizamos uma série de webinars em duas partes tratando de questões de sensibilidade de parâmetros:
  • Procedimentos armazenados, parâmetros, problemas…
    Kimberly L. Tripp e Aaron Bertrand
    24 de janeiro
    Perdeu? Cadastre-se para assistir agora!
  • Enfrentando a detecção de parâmetros usando o SentryOne
    Aaron Bertrand, Kimberly L. Tripp e Andy Mallon
    31 de janeiro
    Perdeu? Assista agora!

Algumas perguntas surgiram durante os dois webinars, e pensei em compilá-las e respondê-las aqui (algumas das respostas vieram de Andy durante o webinar).

Em um problema que vimos recentemente, estamos vendo planos sendo retirados do cache muito rapidamente. Não estamos realizando nada que você descreve (DBCC FREEPROCCACHE etc); a pressão da memória também pode fazer com que isso aconteça?

Sim, a pressão da memória pode ser um fator (veja este post), e eu sei que existem algumas investigações sobre possíveis problemas com o gerenciamento de memória do SQL Server nesse sentido também.

De um participante:"Não é uma pergunta, mas um comentário para o usuário perguntando sobre as muitas vezes que o cache do seu plano é esvaziado. Tivemos isso também e, de fato, foi pressão de memória. Tínhamos a memória máxima do servidor configurada incorretamente, isso foi corrigido usando a fórmula mencionada aqui e, em seguida, tivemos o procedimento deste artigo sendo executado a cada 10 minutos (temos toneladas de SQL dinâmico, usado apenas uma vez)."

E se você usar OR na cláusula where em vez de AND , o problema persistiria?

Normalmente, se você usar OR nesse tipo de padrão, você obterá todas as linhas sempre, a menos que cada parâmetro seja preenchido com valores que filtram as linhas. Isso altera a semântica da consulta de "todas essas coisas precisam ser verdadeiras" para "qualquer uma dessas coisas pode ser verdadeira". Ainda assim, o plano compilado para o primeiro conjunto de parâmetros ainda será armazenado em cache e persistido para execuções futuras, se suas cláusulas usarem AND ou OR .

Isso é 1=1 sinalizar uma boa abordagem? Não é melhor adicionar apenas os parâmetros fornecidos e, portanto, evitar o feio 1=1 ?

O 1 = 1 é praticamente ignorado pelo SQL Server, mas permite que todas as cláusulas condicionais sejam adicionadas com AND para que você não precise tratar o *primeiro* de forma diferente. Aqui está a alternativa:
SET @IncludedWhereClauseYet bit = 0;
SET @sql = N'SELECT cols FROM dbo.Table';
 
IF @param1 IS NOT NULL
BEGIN
  IF @IncludedWhereClauseYet = 0
  BEGIN
    SET @sql += N' WHERE ';
    SET @IncludedWhereClauseYet = 1;
  END
  ELSE
  BEGIN
    SET @sql += N' AND ';
  END
  SET @sql += N' @param1 = @param1';
END
 
IF @param2 IS NOT NULL
BEGIN
  IF @IncludedWhereClauseYet = 0
  ...
END
...

O 1=1 permite que você simplifique, permitindo que você sempre prefixe qualquer cláusula com AND . O código acima fica:
SET @sql = N'SELECT cols FROM dbo.Table WHERE 1 = 1';
 
IF @param1 IS NOT NULL
BEGIN
  SET @sql += N' AND @param1 = @param1';
END
 
IF @param2 IS NOT NULL
BEGIN
  SET @sql += N' AND @param2 = @param2';
END

Talvez você possa usar uma cláusula inicial diferente para evitar todas as condicionais, como WHERE PrimaryKey > 0 ou WHERE PrimaryKey IS NOT NULL , e então cada cláusula subsequente poderia começar com AND . Mas 1 = 1 , embora feio, é inofensivo, e IMHO não é menos feio do que adicionar uma cláusula *real*, mas sem sentido, exceto que uma cláusula *real* pode afetar o plano.

Lembre-se de que quando você está construindo código T-SQL com T-SQL, você tem dois aspectos de "feio" para pensar - às vezes você estará solucionando o código acima e às vezes você estará solucionando a consulta que sai de isto. Tenha cuidado ao sacrificar um pelo bem do outro.

QUE?! Eu perdi totalmente isso... WITH RECOMPILE . Achei que isso esvaziou o plano, mas deixa pra lá só pra essa execução... isso é muito importante saber!

Apenas certifique-se de estar ciente das desvantagens também.
Veja este ótimo post de Paul White.

É OPTION OPTIMIZE FOR @parametername UNKNOWN não é mais preferido em versões SQL mais recentes?

Não acho que seja melhor ou pior nas versões modernas do que quando foi introduzido pela primeira vez no SQL Server 2008. Até onde sei, mesmo com todas as alterações no otimizador e no estimador de cardinalidade, esse bit ainda se comporta da mesma maneira.

Existe alguma carga no servidor, se eu habilitar a captura de estatísticas de procedimento e estatísticas de consulta no SentryOne?

A coleção de estatísticas de procedimento e consulta deve estar ativada por padrão. Toda coleta de dados tem um custo, mas o SQL Sentry é bastante cuidadoso com o custo incorrido pela coleta.

A busca no RS não estava usando isso como um predicado residual, estava procurando em outra coisa que eu não conseguia ver.

Obrigado, vou revisitar esse exemplo e escrever sobre as demonstrações separadamente, certificando-me de incluir todos os detalhes relevantes que não eram óbvios apenas no diagrama de plano.

Não é verdade que adicionar algumas das colunas necessárias como INCLUDE s não tornam o índice mais eficaz porque a pesquisa de chave não será eliminada? Estou pensando que a porcentagem não deve mudar, a menos que você realmente elimine a pesquisa de chave.

Estritamente, sim, isso é verdade. A consulta original foi um mau exemplo primordial, usando SELECT * e um índice faltando um número desesperador de colunas. O ponto que eu estava tentando fazer é que a guia Análise de Índice incentiva você a (a) melhorar a consulta e (b) fazer a cobertura do índice. A pontuação está lá para incentivá-lo a fazer um ou ambos – se você alterar a consulta para precisar de menos colunas, o índice também estará mais próximo de cobrir a consulta. Se você for criar um índice de cobertura novo e separado, também terá as informações sobre quais colunas são necessárias para cobrir essa consulta específica. Tecnicamente, você está certo, adicionar uma coluna de inclusão, mas ainda exigir uma pesquisa para outras 4, não fará com que essa consulta específica tenha um desempenho melhor e não melhorará o índice, mas indica que você está se aproximando. A esperança é que você não pare de adicionar apenas uma coluna de inclusão e ignore o resto. Não sabemos quando você vai parar, então não sei se existe uma solução perfeita – certamente não queremos desencorajar usuários de tornar seus índices mais adequados para suas consultas.

Por que estamos vendo consultas usando o parâmetro de primeiro nome e o parâmetro de sobrenome resumidos em uma instrução usando apenas um parâmetro de sobrenome?

ATUALIZAÇÃO: Isso é intencional. O agrupamento em Mostrar totais agrupa o mesmo procedimento chamado com todas as várias combinações de parâmetros. Assim, você pode usá-lo primeiro para determinar quais parâmetros tendem a causar o pior desempenho e, em seguida, analisar se há ou não distorção de dados. Um parâmetro que leva a uma pesquisa em uma coluna não indexada, por exemplo, provavelmente aparecerá no topo de forma bastante confiável, e você pode ver isso em combinação com outros parâmetros que são passados ​​e também comparados com todas as chamadas em que esse parâmetro não foi passou.

Dito tudo isso, procuraremos ajustar esse comportamento de agrupamento à medida que finalizamos as alterações atualmente em andamento para a tela Top SQL.

Existe alguma documentação sobre como usar um guia de plano? Eu atualmente não teria idéia de como fazer isso.

Isso é outra coisa que eu queria escrever no blog, mas a Microsoft tem alguns tópicos aqui enquanto isso (e confira todos os links relacionados na barra lateral).

Preciso habilitar algo para obter o gráfico do histórico de consultas?

Não, isso deve ser habilitado em todas as versões modernas do aplicativo cliente SentryOne. Se você não estiver vendo, tente Tools > Reset Layout; se isso não funcionar, entre em contato com [email protected].

Há casos em que forçar o último plano válido conhecido usando o Repositório de Consultas quando uma regressão de plano é considerada uma má ideia? Isso tenderá a ocultar problemas que são mais bem resolvidos alterando a declaração como você mostrou?

Forçar um plano geralmente é uma opção de último recurso, e costumo reservá-lo para casos em que você realmente não pode corrigir a declaração (ou alterar o índice). Forçar um plano sempre pode levar ao comportamento errado, porque ainda é um ser humano fazendo essa escolha, e você pode estar fazendo isso com base em informações ruins. A regressão pode ser por causa de uma mudança de plano, mas se você está julgando uma regressão porque o tempo de execução foi mais longo, você investigou outras razões possíveis? Por exemplo, digamos que o sistema foi reinicializado ou houve um failover e obteve um novo plano porque o antigo foi despejado, e talvez as estatísticas também tenham mudado nesse meio tempo, mas agora a consulta é executada por mais tempo, não porque o plano é pior, mas sim porque os buffers estavam vazios. Então, sim, eu certamente não sugeriria forçar um plano em cada regressão.

O SentryOne nem sempre está capturando dados ou parâmetros o tempo todo, então não tenho informações suficientes. Como posso garantir que o SentryOne capture parâmetros e planos de execução o tempo todo?

Você realmente não pode porque tudo se resume a como suas consultas são executadas, como as capturamos e com que rapidez elas são executadas. Muitas vezes, suas consultas não são executadas por tempo suficiente para serem capturadas totalmente, e devemos confiar nas visualizações de estatísticas de consulta/procedimento agregadas do SQL Server, que não coletam informações de parâmetros. Você pode alterar as configurações de coleta para a Origem do SQL principal para capturar mais e em um intervalo mais frequente, mas precisa equilibrar a quantidade de dados coletados com a quantidade de informações adicionais adquiridas.

Posso consultar as informações para automatizar e gerar relatórios?

Não temos nada pronto para você fazer isso, mas deixe-me levar de volta à equipe e ver que tipo de opções podemos apresentar. Uma coisa com a qual brinquei para este webinar foi criar uma Condição de Aconselhamento para capturar os tipos de regressões que estamos procurando, mas o tempo se tornou um fator.

Como decidimos quando usar OPTION (RECOMPILE) , como todos os dias temos planos diferentes para parâmetros diferentes?

Eu diria que comece com as consultas que mais flutuam com a sensibilidade dos parâmetros. Se eu tiver uma consulta que às vezes leva 2 segundos, mas às vezes leva 30, e outra que varia de 4 segundos a 6 segundos,
vou focar na primeira.

Qual é melhor usar, OPTION (RECOMPILE) ou QUERYTRACEON , no caso de sniffing de parâmetros.

Eu prefiro OPTION (RECOMPILE) por duas razões. Um, é auto-documentado; ninguém lendo o código vai se perguntar o que ele está fazendo, mas nem todo mundo lendo o código terá números TF memorizados como 4136. Dois, não requer permissões elevadas – tente usar QUERYTRACEON como peão.

É possível alertar ou informar sobre procedimentos que demoram mais do que o normal? Mais interessado em procedimentos de alta contagem.

Absolutamente, você pode usar uma Condição de Aconselhamento, mas pode ficar um pouco complicado porque – para procedimentos que às vezes são executados abaixo do limite de coleta – você precisaria comparar instantâneos do DMV de estatísticas do procedimento. Adicionei um lembrete ao blog sobre isso também, pois é algo que ajudei os clientes a implementar no passado.

A Microsoft está tornando o Ajuste Automático o padrão para o Banco de Dados SQL do Azure, incluindo a correção automática do plano. Parece uma boa ideia para você?

Reservarei o julgamento até que eu (ou alguns clientes) tenha brincado com ele. Decidir como sintonizar é bastante desafiador para os mortais; mortais escrevendo software para ajustar para você parece pelo menos tão desafiador, se não mais. Quando Andy viu essa pergunta, ele mencionou para mim que isso o lembrava do SQL Server 2000 – o argumento de marketing na época era que era tão auto-ajustável que não precisaríamos mais de DBAs. Essa afirmação não envelheceu bem.

Ser capaz de selecionar os dois pontos no gráfico do histórico de consultas e comparar seria bom.

Concordo.
Fique atento.