Como desenvolvedor de software e aspirante a DBA, tento incorporar as melhores práticas ao projetar meus bancos de dados do SQL Server (99% do tempo em que meu software fica sobre o SQL Server). Eu faço o melhor design possível antes e durante o desenvolvimento.
Mas, assim como qualquer outro desenvolvedor de software, há funcionalidade adicional, bugs e apenas mudança de requisitos que exigem objetos de banco de dados alterados/criados.
Minha pergunta é: o ajuste de consulta deve ser proativo ou reativo? Em outras palavras, algumas semanas após alguma modificação pesada de código/banco de dados, devo reservar um dia para verificar o desempenho da consulta e ajustar com base nisso? Mesmo que pareça estar funcionando bem ?
Ou devo apenas estar ciente de que o desempenho abaixo da média deve ser uma verificação do banco de dados e voltar ao proverbial quadro-negro?
O ajuste de consulta pode levar muito tempo e, dependendo do design inicial do banco de dados, pode ser um benefício mínimo. Estou curioso quanto ao modus operandi aceito.
Ambos, mas principalmente proativos
É importante testar durante o desenvolvimento contra volumes realistas e qualidade de dados. É incrivelmente comum ter uma consulta em execução em um desenvolvedor de 100 ou 1.000 linhas e, em seguida, falhar com 10 milhões de linhas de produção.
Ele permite que você faça anotações também sobre "o índice pode ajudar aqui". Ou "revisite-me". Ou "irá corrigir com o novo recurso xxx na próxima versão do banco de dados".
No entanto, algumas consultas não resistirão ao teste do tempo. A distribuição de dados muda ou torna-se exponencial porque o otimizador decide usar um tipo de junção diferente. Nesse caso, você só pode reagir.
Dizer que, pelo menos para o SQL Server, as várias consultas DMV de "índice ausente" e "consulta mais longa" podem indicar áreas problemáticas antes da ligação
Editado: para esclarecer...
Proativo não significa ajustar todas as consultas agora. Significa ajustar o que você precisa (executar com frequência) para um tempo de resposta razoável. Ignore principalmente as consultas de relatórios semanais das 3 da manhã de domingo.
OK, vou morder e ter uma visão contrária. Em primeiro lugar, eu diria que você nunca deve começar fazendo algo que sabe que o levará a problemas. Se você quiser chamar isso de aplicação de práticas recomendadas, vá em frente. Isso é o mais longe que deve ser proativo.
Depois disso, é desperdício de tempo (e dinheiro), então continue e entregue seu produto. Em vez de fazer uma tonelada de consultas de ajuste de tempo de design que podem ou nunca se tornarem gargalos, use esse tempo para testes extras, incluindo testes de carga.
Quando você descobrir que algo não está funcionando de acordo com suas especificações de design, ou se algo está caindo nos 10% ou 20% inferiores da lista de tempos de resposta do seu criador de perfil, invista o tempo necessário para ajustar o que quer que seja. quebrado.
Em um mundo perfeito, tudo seria projetado perfeitamente desde o início e desenvolvido usando uma sequência de construção lógica. No mundo real, há restrições de orçamento e tempo e seus dados de teste podem acabar não se parecendo com seus dados de produção. Por esta razão, digo para usar o bom senso para evitar problemas de forma proativa, mas concentre seus recursos limitados ajustando as coisas que se tornam problemas reais, em vez de gastar tempo e dinheiro que você provavelmente não tem procurando por problemas imaginários ou potenciais.
Você fará 3 tipos de ajuste, 1 reativo e 2 proativo.
Reativo
Do nada, alguma consulta começa a causar problemas. Pode ser devido a um bug ou recurso do aplicativo, uma tabela crescendo além das expectativas, um pico de tráfego ou o otimizador de consulta ficando "criativo". Isso pode ser um caso do tipo oh-crap-the-site-down no meio da noite, ou pode ser em resposta à lentidão do sistema de natureza não crítica. De qualquer maneira, o caráter definidor do ajuste reativo é que você já tem um problema . Nem é preciso dizer que você quer fazer o mínimo possível disso. O que nos leva a...
Proativo
Tipo 1: Manutenção de Rotina
Em algum tipo de programação, a cada poucos meses ou semanas, dependendo da frequência com que seu esquema muda e da rapidez com que seus dados crescem, você deve revisar a saída das ferramentas de análise de desempenho de seu banco de dados (por exemplo, relatórios AWR para DBAs Oracle). Você está procurando por problemas incipientes, ou seja, coisas que estão a caminho de exigir ajuste reativo, bem como frutas ao alcance da mão, itens que provavelmente não causarão problemas em breve, mas podem ser melhorados com pouco esforço na esperança de evitar - problemas futuros. Quanto tempo você deve gastar com isso dependerá de quanto tempo você tem e no que mais você poderia gastá-lo, mas a quantidade ideal nunca é zero. No entanto, você pode facilmente reduzir o valor que precisa gastar fazendo mais...
Tipo 2: Design Adequado
A advertência de Knuth contra a "otimização prematura" é amplamente conhecida e devidamente respeitada. Mas a definição adequada de "prematuro" deve ser usada. Alguns desenvolvedores de aplicativos, quando autorizados a escrever suas próprias consultas, tendem a adotar a primeira consulta que encontram e que é logicamente correta e não se importam com o desempenho, presente ou futuro. Ou eles podem testar um conjunto de dados de desenvolvimento que simplesmente não é representativo do ambiente de produção (dica: não faça isso! Os desenvolvedores devem sempre ter acesso a dados realistas para teste). O ponto é que o momento adequado para ajustar uma consulta é quando ela é implantada pela primeira vez, não quando ela aparece em uma lista de SQL de baixo desempenho e, definitivamente, não quando causa um problema crítico.
Então, o que se qualificaria como uma otimização prematura na terra do DBA? No topo da minha lista estaria sacrificar a normalização sem uma necessidade demonstrada. Claro que você poderia manter uma soma em uma linha pai em vez de calculá-la em tempo de execução a partir das linhas filhas, mas você realmente precisa? Se você é Twitter ou Amazon, a desnormalização estratégica e o pré-cálculo podem ser seus melhores amigos. Se você estiver projetando um pequeno banco de dados de contabilidade para 5 usuários, a estrutura adequada para facilitar a integridade dos dados precisa ser a principal prioridade. Outras otimizações prematuras também são uma questão de prioridades. Não gaste horas ajustando uma consulta que é executada uma vez por dia e leva 10 segundos, mesmo que você ache que pode cortá-la para 0,1 segundo. Talvez você tenha um relatório executado por 6 horas diárias, mas explore agendá-lo como um trabalho em lote antes de investir tempo em ajustá-lo. Não invista em uma instância separada de relatórios replicados em tempo real se a carga de produção nunca flutuar acima de 10% (supondo que você possa gerenciar a segurança).
Ao testar dados realistas, adivinhar os padrões de crescimento e tráfego (além de concessões para picos) e aplicar seu conhecimento sobre as peculiaridades do otimizador de sua plataforma, você pode implantar consultas que são executadas (quase) de maneira ideal não apenas agora, mas no futuro , e em condições abaixo do ideal. Quando você aplica as técnicas adequadas, o desempenho da consulta pode ser previsto com precisão e otimizado (no sentido de cada componente ser tão rápido quanto necessário).
(E enquanto você está nisso, aprenda estatísticas! )
Em um mundo perfeito, todos os ajustes seriam feitos na fase de projeto de forma proativa e nada seria reativo, mas o mundo não é perfeito. Você descobrirá que os dados de teste às vezes não são representativos, os casos de teste foram perdidos, as cargas serão inesperadamente diferentes e haverá bugs que causam problemas de desempenho. Essas situações podem exigir algum ajuste reativo, mas isso não significa que o ajuste reativo seja o preferido. O objetivo deve ser sempre pegá-los na frente.
Seu planejamento para ajuste retroativo é muito pragmático. Quando estiver testando, você deve documentar os tempos esperados e o rendimento e, às vezes, deve realmente criar uma análise que permita saber quando os processos de produção não estão atendendo às especificações do projeto. Dessa forma, você poderá identificar com antecedência qual código precisa ser ajustado. Você pode determinar não apenas qual é o problema, mas por que você não o detectou na fase de design/teste.
Para mim, o teste de desempenho sempre fez parte do processo de desenvolvimento. Deseja alterar esta tabela, alterar este relatório, adicionar este recurso? Como parte do teste, certifique-se de poder comparar o desempenho individual e geral com linhas de base conhecidas e/ou com os requisitos (por exemplo, alguns relatórios executados em segundo plano ou automatizados, de modo que o desempenho - ou melhor, a velocidade - de cada consulta individual no sistema nem sempre é a prioridade máxima).
IMHO, isso não deve ser um processo reativo - você nunca deve esperar até que uma alteração cause um problema de desempenho na produção para começar a reagir a ela. Ao fazer a alteração no desenvolvimento/teste etc., você deve testar essas alterações com dados semelhantes em hardware semelhante com os mesmos aplicativos e padrões de uso semelhantes. Não deixe que essas mudanças cheguem às pressas para a produção e o surpreendam. Isso quase sempre acontecerá quando não for conveniente passar um dia sintonizando - faça um orçamento para esse tempo de sintonização com bastante antecedência.