Desempenho – um problema normalmente aplicacional

Na secção Bottleneck Elimination do artigo Database Performance Tuning Guide, é afirmado que, muitas vezes, a maneira mais efectiva de resolver um problema de congestionamento em base-de-dados passa por alterar a aplicação subjacente. Posso afirmar que mais de 95% dos melhoramentos de desempenho que consegui resultaram da sugestão de alteração de aplicações. Neste texto, conto uma breve história de como um problema aplicacional se pode assemelhar a um problema de congestionamento da base-de-dados.

A aplicação em questão assenta em SQL Server e permite gerir a transferência de equipamentos entre localizações no seio da empresa. Num dos procedimentos habituais do funcionamento da aplicação, começou a surgir o erro ao fim de alguns anos de utilização:

Timeout expired. The timeout period elapsed prior to completion of the operation

É natural assumir que alguma consulta se tornou subitamente mais lenta porque algo foi modificado ao nível do servidor ou porque os índices envolvidos se fragmentaram. Foi esta suposição que levou o responsável do desenvolvimento a contactar-me. Relativamente ao servidor, nenhuma configuração fora efectuada e, portanto, o problema dever-se-ia centrar na consulta.

Recorri ao SQL Monitor para determinar quais teriam sido as consultas mais pesadas a serem executadas na base-de-dados numa janela temporal centrada em torno do evento. Verifiquei que as consultas mais lentas executavam em algumas centenas de milissegundos e não encontrei tempos de espera (waits) nem tampouco bloqueios (locks).

A experiência tem-me mostrado que um determinado procedimento aplicacional não envolve apenas uma consulta e, por isso, decidi averiguar quais teriam sido as consultas que, no total das suas execuções, requereram o maior tempo de processamento. Determinei que uma consulta cuja execução individual era extremamente rápida executara milhares de vezes num intervalo de tempo muito curto. Estaria este fenómeno relacionado com o erro encontrado?

Contactei o responsável do desenvolvimento e expus-lhe o resultado. Não se encontrando convencido e tendo a aplicação funcionado até à data sem problemas, pediu-me que reconstruísse os índices associados. Após a reconstrução dos índices, o problema persistiu. Sugeri-lhe, portanto, que depurasse a aplicação de modo a despistar a minha hipótese. Bastou um ponto de paragem na linha referenciada pela excepção para descobrirmos o problema que passo a explicar.

Suponhamos que a base-de-dados possui uma tabela de equipamentos que se classificam em vários tipos. As transferências de diferentes tipos de equipamentos podem seguir trâmites diferentes e requerem a geração automática de diferentes números de controlo. Os números de controlo geram-se, para cada tipo de equipamento, adendando um prefixo ao sucessor numérico do resultado da contagem dos equipamentos de um determinado tipo. Por exemplo, se existissem 10 equipamentos do tipo EquipamentoA e fosse acrescentado um novo equipamento desse tipo, seria gerado o número de controlo A_11. Após a geração do número de controlo, era verificada a sua existência na base-de-dados e, em caso afirmativo, a mesma função era chamada para determinar um novo número de controlo.

Suponhamos agora que o equipamento com o número A_9 foi removido. A contagem dos equipamentos do tipo EquipamentoA passa a ser novamente 10. O número de controlo A_11 gerado existe na base-de-dados. Como a função que gera o número de controlo é a mesma, este será novamente A11 que existe na base-de-dados. Numa situação normal, a aplicação manter-se-ia em ciclo infinito. Quando o processo é envolto por uma transacção, a aplicação executa até exaurir o tempo máximo definido para as transacções.

A aplicação funcionara durante tanto tempo sem que o erro tivesse sido detectado porque nunca antes tinham sido removidos equipamentos da tabela em questão. Em conclusão, só porque uma aplicação deixou subitamente de funcionar ao fim de vários anos se assume que o problema está no seu ambiente é um pressuposto que pode não se adequar à realidade. É útil, no contexto de uma análise de performance, ter em conta, não só as consultas mais exigentes, como a possibilidade de um número excessivo de consultas estar associada a um processo simples devido a erros de implementação. Trata-se de uma situação comum quando se usam O/RM como a Entity Framework ou o NHibernate quando não se tem em conta as melhores práticas na sua utilização.

Sobre Sérgio O. Marques

Licenciado em Física/Matemática Aplicada (Astronomia) pela Faculdade de Ciências da Universidade do Porto e Mestre em Matemática Aplicada pela mesma instituição. Actualmente, exerço a função de Administrador de bases-de-dados. Dentro o meu leque de interesses encontram-se todos os temas afins às disciplinas de Matemática, Física e Astronomia. Porém, como entusiasta, interesso-me por temas relacionados com electrónica, poesia, música e fotografia.
Esta entrada foi publicada em Computadores e Internet, Sem categoria com as etiquetas , , , , . ligação permanente.

Deixe um comentário