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

Planos diferentes para servidores idênticos


No meu último post, "Planos múltiplos para uma consulta 'idêntica'", falei sobre o caso em que você está obtendo dois planos diferentes para o que você acha que é a mesma consulta, bem como o caso em que você está obtendo duas cópias do mesmo plano (e talvez nem saiba). Como examinamos lá, "idêntico" pode ser uma palavra bastante forte.

Outro cenário que leva as pessoas a um loop é o caso em que restauram um banco de dados em um servidor diferente – digamos, restauram um banco de dados de produção em um servidor de teste "idêntico" – e obtêm características de desempenho diferentes ou planos diferentes para a mesma consulta (não citações desta vez - estou realmente falando de consultas verdadeiramente idênticas).

Os servidores são realmente "idênticos"?

Esses caras podem parecer semelhantes, mas não são exatamente idênticos.
Se você se deparar com esse cenário, a primeira coisa que você precisa se perguntar é se esses dois servidores são realmente idênticos. Algumas coisas para verificar:
  • Versão – Muitas alterações de comportamento de consulta e otimizador são enviadas por meio de service packs e atualizações cumulativas. Muitas vezes tenho visto pessoas dizerem:"Bem, ambos são de 2008!" – quando, na verdade, um era 2008 e o outro era 2008 R2, ou estavam em service packs diferentes ou mesmo em níveis de atualização cumulativa. Como muitas pessoas que lêem @@VERSION confundem as informações do service pack do sistema operacional com as informações do service pack do SQL Server, eu diria que o seguinte é melhor:
    SELECT SERVERPROPERTY (N'ProductVersion' );

    Eu não posso enfatizar o suficiente a importância de usar exatamente a mesma versão para realizar testes verdadeiros, de maçãs com maçãs. Se você estiver usando o SQL Server 2012 ou superior, poderá verificar nossas postagens de compilação (SQL Server 2012 | SQL Server 2014) para determinar o service pack ou a atualização cumulativa necessária para garantir que as versões correspondam.
  • Edição – Embora esperemos que você esteja usando a mesma edição em ambos os servidores (ou equivalente, pois além do licenciamento, Desenvolvedor e Avaliação são os mesmos que Enterprise), as incompatibilidades aqui podem levar a um comportamento muito diferente. Por exemplo, diferentes edições têm diferentes capacidades de computação para vários recursos e, em seguida, há coisas mais sutis, como a capacidade de usar uma exibição indexada sem a dica NOEXPAND ou realizar alterações de esquema ou manutenção de índice online. Você pode comparar as edições usando:

    SELECT SERVERPROPERTY (N'Edition' );
  • Contagem de CPU – O SQL Server definitivamente usa o número de agendadores disponíveis durante o processo de produção de um plano de execução, e não há como negar que o número de núcleos pode afetar o desempenho real do tempo de execução (deixemos de fora a velocidade do clock, pois isso raramente é um fator significativo na consulta atuação). Não apenas valide o número de núcleos instalados fisicamente no servidor subjacente, mas também verifique o log de erros do SQL Server para o número de CPUs que o SQL Server pode realmente usar devido ao licenciamento. Mesmo esquecendo a contagem bruta de núcleos, em um sistema NUMA, restrições artificiais aqui podem levar a perfis de desempenho muito diferentes. Para obter mais informações, consulte a postagem recente de Brent Ozar, "Why Core-Based Licensing Matters for Performance Tuning". A edição também se encaixa aqui, pois no SQL Server 2012 e 2014, a Standard Edition pode usar apenas 16 núcleos, independentemente do que suas configurações ou hardware físico possam fazer você acreditar. Outras configurações que podem influenciar a escolha e o desempenho do plano baseado em CPU de maneira diferente incluem o Resource Governor, MAXDOP em todo o servidor, afinidade de CPU e limite de custo para paralelismo.
  • Quantidade de memória – Assim como as CPUs, o otimizador faz escolhas de planos com base na quantidade de memória disponível. E como as CPUs, não estou falando apenas da quantidade de RAM instalada no sistema, mas da quantidade de memória concedida ao SQL Server e quanto ele está realmente usando. Verifique as configurações de memória máxima do servidor, mas também os contadores de desempenho para memória total e de destino e até mesmo DBCC MEMORYSTATUS. Outras coisas que você pode querer revisar incluem as configurações do Administrador de Recursos e Bloquear Páginas na Memória. Há também uma configuração que, se diferente entre dois servidores, pode ter um efeito significativo em quanto do cache do plano está em uso para o mesmo conjunto de consultas:otimizar para cargas de trabalho ad hoc. Kimberly Tripp tem um ótimo post sobre isso:Planeje o cache e otimize para cargas de trabalho adhoc. Por fim, se o servidor for virtual, esteja ciente de que o ambiente pode desempenhar um papel aqui – especialmente quando as configurações de memória da VM não correspondem à produção ou são dinâmicas.
  • Buffer pool/cache do plano – Quando você restaura o banco de dados no servidor de teste, há várias coisas que simplesmente não estão prontas para você imediatamente. O pool de buffers não contém nenhum dado que possa ter existido no servidor de origem – portanto, haverá E/S adicional necessária para preparar os dados na memória na primeira vez que forem consultados. E se o pool de buffers for restrito de forma diferente da produção devido a alguns dos fatores acima, pode não ser possível alcançar os mesmos padrões de desempenho mesmo depois de executar a consulta várias vezes – Paul White (@SQL_Kiwi) fala sobre isso em sua resposta em Administradores de banco de dados. Além disso, o cache do plano não conterá nenhum dos planos que existiam na produção, portanto, no mínimo - mesmo que o mesmo plano seja compilado (o que pode não acontecer devido a parâmetros diferentes de quando o plano foi compilado no original server) – você terá custos adicionais de compilação. E isso também pode mudar se você tiver sinalizadores de rastreamento que afetem o plano.
  • Subsistema de disco – Embora a velocidade e o tamanho do(s) disco(s) usado(s) não afetem diretamente a escolha do plano, eles certamente podem influenciar o desempenho observado, o que pode fazer você se perguntar por que a mesma consulta, com o mesmo plano, é executada muito mais rápido em um sistema do que o outro. Normalmente, a E/S é o maior gargalo do SQL Server e é bastante raro que um servidor de teste realmente tenha exatamente o mesmo subsistema subjacente que seu equivalente de produção. Portanto, se você estiver vendo diferenças de desempenho entre os dois sistemas e os planos e outros elementos de hardware forem os mesmos, este pode ser o próximo melhor local para verificar. E não se esqueça de que, a partir do SQL Server 2014, o Resource Governor pode impor restrições ao desempenho de E/S.
  • Sinalizadores de rastreamento – Verifique a lista de sinalizadores de rastreamento globais definidos em ambos os servidores; há vários que podem afetar a otimização, o comportamento do plano e o desempenho percebido, mesmo que todas as configurações acima sejam idênticas. Aqui estão 10 comuns e notáveis ​​(embora isso não seja absolutamente um endosso para ativar qualquer um deles sem testes de regressão completos):


    Sinalizador Explicação
    2301 Coage o otimizador a gastar mais tempo tentando encontrar um plano ideal.
    2312 Força o novo estimador de cardinalidade do SQL Server 2014.
    2335 Provoca concessões de memória mais conservadoras.
    2453 Força OPTION (RECOMPILE) para consultas que fazem referência a variáveis ​​de tabela.
    2861 Permite que o SQL Server armazene em cache planos triviais / de custo zero.
    4136 Efetivamente, adiciona OPTIMIZE FOR UNKNOWN a todas as consultas (para impedir a detecção de parâmetros).
    4199 Um guarda-chuva contendo várias correções de otimizador.
    8744 Desativa a pré-busca para loops aninhados.
    9481 Desativa o novo estimador de cardinalidade do SQL Server 2014.


    Essa lista de sinalizadores de rastreamento não é exaustiva; há muitos outros, incluindo os não documentados que me pediram para não mencionar. Se você estiver usando outros não listados acima (e não puder explicar o motivo), poderá encontrar pistas no KB #920093, KB #2964518, Trace Flags (MSDN) ou Trace Flags in SQL Server (TechNet). Você também encontrará informações valiosas em várias postagens de Paul White, aqui ou em sql.kiwi.
  • Simultaneidade – Presumivelmente, o sistema de teste é usado para outras coisas além do que você está testando no momento. E, a menos que você esteja executando algum tipo de repetição, provavelmente também terá um perfil de carga de trabalho muito diferente. Obviamente, essas diferenças na carga de trabalho podem ter um impacto direto na disponibilidade de recursos para atender às solicitações que você está testando e, por sua vez, no desempenho percebido dessas solicitações. Não se esqueça de verificar se há outros serviços que podem não existir em produção ou que existem, mas são usados ​​de maneiras diferentes (como Analysis Services, Reporting Services, serviços do Windows e até mesmo seus próprios aplicativos). Por outro lado, pode haver serviços como esse na produção que afetam o desempenho ou sobrecarga adicional na própria instância que não é imitada no teste:além da carga de trabalho de produção real, pense em coisas como rastreamento, eventos estendidos, monitoramento de alto impacto, controle de alterações, captura de dados de alterações, auditoria, agente de serviços, manutenção de índice, tarefas de backup, verificações de DBCC, espelhamento, replicação, grupos de disponibilidade e a lista continua…

Os bancos de dados ainda são "idênticos"?


Supondo que todas as variáveis ​​de hardware e carga de trabalho correspondam bem o suficiente, ainda pode ser um desafio garantir que os bancos de dados permaneçam os mesmos. Se você estiver executando um backup/restauração no sistema de teste, o novo banco de dados começará idêntico à origem (exceto pela localização física e segurança). Mas assim que você começa a tocá-lo de alguma forma, ele rapidamente se desvia da cópia de produção, pois você pode fazer um ou todos os seguintes:
  • Alterar dados, esquema ou ambos.
  • Inicie inadvertidamente uma atualização automática de estatísticas.
  • Adicione, desfragmente ou reconstrua índices manualmente ou crie ou atualize estatísticas.
  • Altere as configurações do banco de dados, como nível de compatibilidade, nível de isolamento, parametrização forçada, índices XML seletivos ou qualquer uma das opções denominadas "Auto"-. (Heck, mesmo os locais de dados e arquivos de log e as configurações de crescimento podem afetar o desempenho da consulta, e isso inclui tempdb.)
  • Esvazie o cache do plano, o pool de buffers ou ambos, diretamente ou como efeito colateral de outros eventos (como RECONFIGURE ou reinicialização de serviço).

Além disso, uma vez que você comece a gerar novos planos de consulta, mesmo antes de qualquer uma das alterações acima, lembre-se de que eles podem ser baseados em dados diferentes dos dados usados ​​para gerar planos para as mesmas consultas em produção. Por exemplo, a cardinalidade quando o plano foi compilado em produção pode ter oscilado significativamente entre esse ponto e o momento do backup, o que significa que o novo plano será gerado com base em diferentes estatísticas e informações de histograma.

Essas coisas divergem ainda mais se isso não for, de fato, uma restauração recente – mas sim dois esquemas e conjuntos de dados que você está mantendo sincronizados de outras maneiras (como implantações manuais de alterações de esquema e/ou dados, ou mesmo replicação). Devido às limitações de espaço em disco, você também pode ter obtido apenas um subconjunto de dados de produção, ou até mesmo um clone apenas de estatísticas – essas diferenças nos dados quase certamente levarão a diferentes características de desempenho para todas as consultas, exceto as mais simples, mesmo se você fizer isso sorte e obter os mesmos planos para alguns.

As consultas são realmente "idênticas"?


Mesmo que tudo acima dê certo, ainda há cenários em que você está obtendo um plano diferente devido às configurações da sessão (você pode estar usando uma cópia diferente do SSMS, com configurações diferentes ou uma ferramenta de cliente totalmente diferente) ou esquemas padrão diferentes ( você pode estar se conectando ao servidor de teste como um login de autenticação Windows ou SQL diferente, por exemplo). Eu falei muito sobre essas coisas no meu post anterior.

Conclusão


Embora existam maneiras de mitigar algumas diferenças (confira DBCC OPTIMIZER_WHATIF para enganar seu servidor de teste para acreditar em coisas fenomenais sobre o hardware subjacente), a verdade é que será muito desafiador fazer dois servidores funcionarem de maneira confiável e consistentemente idênticos, e que existem potencialmente dezenas de razões pelas quais você pode obter planos diferentes ou desempenho diferente em dois servidores semelhantes (ou mesmo idênticos).

Você tem algum truque específico? Você tem algum ponto de dor excruciante com as ideias acima (ou outras que esqueci de mencionar)? Por favor, compartilhe nos comentários abaixo!