Recentemente, me deparei com um problema em que uma procedure estava causando timeout na aplicação. Ao investigar, percebi que a origem do problema estava relacionada à escrita da consulta. Quando a procedure foi inicialmente criada, a tabela era pequena, e o uso do operador OR no WHERE não causava grandes impactos.

A particularidade dessa consulta é que ela possui diferentes condições de filtro, baseadas em um parâmetro @TIPO que varia de 1 a 7. À medida que o volume de dados cresceu, o uso do OR passou a afetar significativamente o desempenho, resultando em timeouts e consumo elevado de recursos.

Uma das maneiras de resolver o problema é transformar a procedure em uma procedure dinâmica, fazendo com que o filtro adotado na query seja adaptado de acordo com o parâmetro passado, otimizando a consulta para cada situação específica.

Criei a procedure pr_organizationlevel2 para simular uma consulta que encontrei em um ambiente de produção. Nessa consulta, temos o parâmetro @TIPO, que pode receber 4 tipos de entrada diferentes, e cada tipo aplica um filtro específico na consulta.

PROBLEMA INICIAL

Na versão original da procedure, utilizávamos a cláusula OR para identificar qual tipo de parâmetro o @TIPO recebeu. Essa abordagem resultava em uma execução lenta pois por conta dos OR o plano ignorava índices e sempre fazia scan, chegando a 35 segundos de tempo de execução, e frequentemente causava timeouts na aplicação. Além disso, a consulta fazia a leitura de 10 milhões de linhas, ou seja, varria a tabela inteira para retornar somente 1 linha.

SOLUÇÃO

Uma maneira eficiente de solucionar esse problema foi transformar a procedure em uma procedure dinâmica. Com essa abordagem, a procedure adota apenas o filtro referente ao @TIPO fornecido, sem a necessidade de varrer a tabela inteira devido ao uso excessivo do OR.

Utilizamos um CASE WHEN para que cada valor de @TIPO adicione um filtro específico à consulta executada dentro da procedure.

Observação: É importante notar que, após o EXEC sp_executesql @sql, é necessário especificar o tipo da variável e, em seguida, passar a variável, conforme mostrado na imagem acima (mais informações no link de apoio).

RESULTADOS

Ao aplicar a procedure dinâmica, obtivemos um ganho significativo em tempo de execução e utilização de recursos do sistema. A consulta ficou muito mais rápida, passou a utilizar o índice e a consumir menos recursos. De fato lendo e retornando somente uma linha.

SCRIPT

LINK DE APOIO

sp_executesql

Deixe um comentário