Por que um aplicativo SQL falador rasteja na VPN e o que agrupar
Uma tela que dispara cem consultas dependentes paga a ida e volta cem vezes. Conte as esperas, agrupe as independentes e depois mova a execução.
Um formulário que abre em menos de um segundo numa LAN leva cinco segundos pela VPN, enquanto a cópia de um arquivo no mesmo link roda em velocidade total. A diferença não é banda. O formulário espera uma sequência de respostas e paga a ida e volta completa em cada passo, enquanto a cópia de arquivo mantém bytes em voo continuamente. Conte essas esperas antes de mexer na linha de acesso.
O sintoma é uma tela, não uma consulta
Cada consulta dessa tela pode ser rápida e a tela ainda pode ser lenta, porque o total é a soma das esperas e não a soma dos tempos de execução. Uma instrução que roda em dois milissegundos ainda custa uma ida e volta inteira quando o cliente precisa receber o resultado antes de enviar a próxima. Num caminho com quarenta milissegundos de latência, cem chamadas dependentes somam cerca de quatro segundos antes de qualquer trabalho de renderização acontecer. Essa aritmética é um modelo da espera, não um benchmark do seu link.
É por isso que um teste de velocidade parece inocente. A transferência em massa mede vazão, um formulário falador mede latência, e uma VPN pode ser excelente numa e continuar comum na outra. Diagnosticar a tela significa, portanto, medir a tela e não o link.
Registre o tempo de ponta a ponta de uma ação do usuário antes de mudar qualquer coisa. Esse número é a única linha de base capaz de dizer se uma correção posterior funcionou.
Conte esperas sequenciais em uma ação do usuário
Instrumente o cliente em vez de adivinhar. No psql, \timing on imprime o tempo decorrido de cada instrução, e EXPLAIN (ANALYZE, BUFFERS) mostra quanto desse tempo o servidor realmente gastou no trabalho.
A diferença entre esses dois números é a sua sobrecarga de rede e de cliente. Se uma instrução executa em dois milissegundos e o cliente registra sessenta, os cinquenta e oito restantes são viagem e processamento local, e nenhum índice vai removê-los. Repita essa comparação para cada instrução que a tela emite e some as diferenças, não os tempos de execução.
Anote o resultado como uma contagem de esperas sequenciais. É essa a grandeza que as duas seções seguintes conseguem reduzir, e é um número sobre o qual se pode discutir com evidências.
Agrupe as chamadas independentes, mantenha as dependentes
Duas instruções que não leem o resultado uma da outra podem viajar juntas e ser coletadas uma vez, o que transforma duas esperas em uma. Duas instruções em que a segunda precisa do valor da primeira não podem, porque a dependência é real e agrupá-las mudaria o que o programa faz. Separe as chamadas nessas duas pilhas antes de reescrever qualquer coisa, e o tamanho de cada pilha diz o que é possível.
O trabalho baseado em conjuntos remove esperas de forma mais completa que o agrupamento. Uma consulta que devolve as linhas que um laço buscava uma a uma elimina o laço e também as idas e voltas. Procure o laço primeiro, porque costuma ser o maior ganho e a mudança mais fácil de revisar.
Um lote ainda precisa preservar o tratamento de erros e os limites de transação. Concatenar instruções não relacionadas numa única string não é uma otimização segura, e um lote que esconde uma instrução falha atrás de um envio bem-sucedido é pior do que as esperas que economizou.
Reutilize conexões antes de comprar banda
Uma nova conexão custa resolução de nome, handshake TCP, negociação TLS e autenticação, e num caminho de alta latência cada um desses é mais uma ida e volta antes da primeira consulta. Pools de conexão existem para pagar esse custo uma vez por processo em vez de uma vez por chamada.
No ADO.NET, fechar ou descartar uma conexão do pool a devolve para reutilização em vez de abrir uma nova conexão física, então o padrão que parece vazamento costuma ser o uso correto. Verifique se o pool está realmente em uso em vez de supor: registre a criação de conexões físicas ou acompanhe a contagem de sessões no servidor enquanto a tela roda. A orientação de desempenho de SQL diz o mesmo sobre reduzir idas e voltas e agrupar chamadas ad hoc frequentes, com exemplos específicos de serviço que você deve mapear para a sua própria implantação.
O pooling remove o custo de preparação e deixa as esperas sequenciais de consulta intactas. É um pré-requisito para uma medição limpa, não uma correção por si só.
Pondere aproximar a execução dos dados
Executar a aplicação perto do banco substitui muitas trocas remotas com o banco por uma única sessão remota de exibição. Para uma carga faladora pode ser uma grande mudança, e é tanto uma mudança operacional quanto de desempenho: gestão de sessões, controle de acesso, implantação de software e experiência do usuário andam todas junto com a aplicação.
Meça a interface real e os dados que ela transfere antes de presumir que alguma direção é mais rápida. Uma sessão de desktop remoto move pixels, e uma tela com gráficos densos pode ter desempenho pior no mesmo caminho do que as consultas que substituiu, especialmente quando o cliente redesenha continuamente.
Depois repita a ação original e compare três números: esperas sequenciais, volume de resultados e tempo de conclusão de ponta a ponta. Uma melhoria que muda a tarefa medida do usuário preservando a correção dos dados e a política de acesso é a que vale a pena manter.