Nexcore

O índice que faltava | Nexcore Insights

Preview — O índice que faltava | Nexcore Insights Nexcore (header sticky simulado) Insights SQL Server Performance Diagnóstico O índice que faltava: como 13 milhões de leituras desnecessárias estavam a travar um ERP em produção Um caso prático de diagnóstico de performance em SQL Server, quando o problema está num produto vertical de terceiros e não controlamos o código. JF Autor Jorge Fernandes Publicado 23 Abr 2026 Leitura 8 minutos 01O sintoma Um cliente nosso opera há anos com um ERP vertical — uma solução específica do sector dele, desenvolvida por um fornecedor português, instalada em dezenas de empresas. A queixa era recorrente: lentidão perceptível numa das operações mais frequentes do dia-a-dia. Nada dramático, nada que parasse a operação. Apenas aquela fricção permanente em que cada acção demora uns segundos a mais do que deveria, multiplicada por dezenas de utilizações diárias, multiplicada por meses. O cliente vivia com o problema há bastante tempo. A percepção generalizada era a habitual nestes casos: «a base de dados está grande», «o servidor precisa de mais RAM», «isto é do Windows». Explicações vagas que não resolvem nada mas acalmam a frustração por uns dias. Quando nos pediram para investigar, a primeira pergunta que nos fizemos não foi «o que está mal?» mas sim «o que está o servidor realmente a fazer quando esta acção é executada?». Essa mudança de enquadramento é, na nossa experiência, metade do caminho para qualquer diagnóstico técnico sério. 02O contexto técnico O servidor corria numa VM com 16 GB de RAM, Windows Server, SQL Server Standard. A base de dados não era pequena, mas também não era obscena — estávamos longe do volume onde a dimensão, por si só, explicaria degradação perceptível em operações transaccionais simples. Sendo um ERP de terceiros, não tínhamos acesso ao código da aplicação. Não podíamos abrir o Visual Studio e pôr um profiler na camada de dados. O que tínhamos era acesso ao SQL Server — e, em 90% dos casos de lentidão em ERPs verticais, isso basta. 03A investigação A abordagem foi directa: em vez de teorizar sobre onde poderia estar o problema, deixámos o próprio SQL Server dizer-nos. O SQL Server mantém estatísticas extraordinariamente detalhadas sobre cada query executada — quantas vezes correu, quantas leituras lógicas fez, quanto tempo de CPU consumiu, qual o pior tempo de execução. Basta saber onde olhar. A query que usámos para extrair o top offenders foi algo como: SQL Copiar SELECT TOP 20 qs.execution_count, qs.total_logical_reads, qs.total_logical_reads / qs.execution_count AS avg_logical_reads, qs.total_worker_time / qs.execution_count AS avg_cpu_time, SUBSTRING(qt.text, qs.statement_start_offset / 2 + 1, (CASE WHEN qs.statement_end_offset = -1 THEN DATALENGTH(qt.text) ELSE qs.statement_end_offset END – qs.statement_start_offset) / 2 + 1) AS query_text FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt ORDER BY qs.total_logical_reads DESC O resultado foi imediatamente revelador. No topo da lista, um DELETE simples numa tabela de parâmetros auxiliares, com apenas três colunas no WHERE. Estatísticas: 1.160 Execuções registadas 11.692 Leituras lógicas por execução 13M+ Leituras lógicas no total Para quem não vive em SQL Server diariamente, o significado prático: uma operação que deveria tocar numa única linha estava a percorrer, em média, 11.692 páginas de dados de cada vez. Em termos humanos, o ERP pedia à base de dados «apaga esta linha» e a base de dados respondia «perfeito, deixa-me ler a tabela inteira primeiro para encontrar qual é». Multiplicado pelo número de vezes que a operação é desencadeada ao longo do dia — e em muitas aplicações empresariais, a mesma query é disparada dezenas de vezes por cada interacção do utilizador — tínhamos a explicação completa para os picos de I/O de disco que o cliente relatava. 04A causa A causa era banal: falta de um índice. A tabela auxiliar não tinha qualquer índice sobre as três colunas que a aplicação usa em praticamente todas as queries que a tocam. Cada SELECT e cada DELETE obrigava o SQL Server a fazer um full table scan — percorrer a tabela linha a linha até encontrar as que interessavam. Em tabelas pequenas, isto passa despercebido. À medida que a tabela cresce — e numa empresa activa, com uso diário do ERP há anos, cresce sempre — o custo de cada operação aumenta proporcionalmente ao tamanho da tabela. O que começou por ser imperceptível aos dois meses de uso torna-se frustrante aos dois anos e insuportável aos cinco. Observação Este é, provavelmente, o padrão de degradação de performance mais comum em ERPs verticais: não há um evento, há uma erosão. Quando o cliente finalmente se queixa, o problema já lá está há muito tempo. 05A solução técnica A solução é quase embaraçosamente simples: SQL Copiar CREATE INDEX IX_Tabela_ColA_ColB_ColC ON TabelaAuxiliar (ColunaA, ColunaB, ColunaC) INCLUDE (ColunaValor) Três colunas no índice, uma coluna adicional incluída para que as queries de SELECT não precisem sequer de voltar à tabela principal para ler o valor (uma técnica chamada covering index). Em tabelas desta dimensão, a criação do índice demora alguns segundos. O efeito é imediato: cada operação passa a tocar numa ou poucas páginas em vez de 11.692. 06A decisão comercial Aqui começa a parte que distingue um técnico competente de um consultor sénior. Tecnicamente, eu podia criar o índice e pronto. Seria invisível para o cliente, resolveria o problema, e provavelmente ninguém dava por nada. Comercialmente, seria um erro. Estávamos a alterar uma base de dados de um produto de terceiros. Uma actualização futura do ERP podia recriar a tabela e eliminar o índice. Se alguma coisa corresse mal mais tarde — uma migração, um upgrade, um problema sem relação — o fornecedor podia sempre apontar o dedo: «vocês mexeram na base de dados». E, do ponto de vista de ecossistema, o fornecedor tem o direito de saber que o produto dele tem um problema de desenho que afecta potencialmente todos os clientes, não apenas este. A decisão foi enviar-lhes um diagnóstico técnico escrito, com as queries de prova, as estatísticas, e a sugestão concreta de índice. Não em tom de denúncia nem de lição, mas como parceiro do ecossistema a reportar