
# Otimizando customizações Protheus: quando parar de processar linha a linha muda tudo
Um dos maiores desafios em customizações Protheus não está apenas na regra de negócio. Muitas vezes, o gargalo real está na forma como a rotina acessa, filtra e grava os dados.
Recentemente trabalhei em uma otimização envolvendo rotinas ligadas à apuração e expectativa de comissão. O resultado foi uma mudança expressiva de desempenho: o processo, que antes dependia de buscas e inclusões linha a linha, passou a executar a maior parte da carga diretamente no banco, com `INSERT INTO ... SELECT`.
## O problema
A rotina original fazia muito processamento procedural:
- percorria vendedores um a um;
- fazia validações repetidas em `SA3` e em tabela customizada de regras;
- utilizava o padrão conhecido como RBAR, *Row By Agonizing Row*, dentro de loops;
- populava tabelas temporárias item a item;
- em alguns cenários, processava mais empresas e filiais do que o necessário.
Esse padrão é comum em customizações antigas: funciona, respeita a regra, mas escala mal. Quando o volume de vendedores, notas, itens ou filiais cresce, cada busca individual vira custo acumulado.
## A estratégia adotada
A primeira decisão foi centralizar a regra de obtenção e montagem dos dados em um único ponto.
Em vez de manter regras parecidas espalhadas entre vários programas, o fluxo foi reorganizado para que exista uma rotina principal responsável pelo cálculo, pela montagem das tabelas temporárias e pela consolidação das informações.
Com isso:
- o documento corrente é identificado no ponto de origem;
- os parâmetros necessários são repassados para a rotina central;
- a rotina central decide se deve processar um relatório completo ou apenas um documento específico;
- a montagem da comissão e dos detalhes passa a ser feita por SQL direto.
Para pedidos, a origem dos dados pode ser composta por tabelas como `SC5/SC6`.
Para orçamentos, a origem pode ser composta por tabelas como `SCJ/SCK`.
A regra de negócio permanece centralizada, mas a origem dos dados muda conforme o contexto.
## Substituindo loop por consulta em lote
Um dos maiores gargalos era a seleção de vendedores usando busca individual na tabela customizada de regras.
O padrão anterior era conceitualmente assim:
```advpl
While SA3->(!Eof())
If REGRA->(BuscaRegra(...))
aAdd(aVendedores,...)
Endif
SA3->(dbSkip())
EndDo
```
A melhoria foi trocar isso por uma carga em lote, usando SQL para juntar `SA3` e a tabela de regras de uma vez.
Isso reduz drasticamente:
- quantidade de round trips;
- troca de contexto entre AdvPL/TLPP e banco;
- uso de alias em loop;
- custo acumulado de busca por vendedor.
A regra permanece a mesma, mas o banco passa a fazer o que ele faz melhor: filtrar, juntar e retornar conjuntos.
## Carga direta nas temporárias
Outro ponto importante foi a criação das tabelas temporárias de comissão e detalhes.
As tabelas continuam sendo criadas com os recursos tradicionais do Protheus, como `CriaTrab()` e `dbCreate()`, mas a alimentação deixou de ser feita com `RecLock()` ou `dbAppend()` linha a linha.
A nova abordagem usa:
```sql
INSERT INTO tabela_temporaria (...)
SELECT ...
FROM ...
JOIN ...
WHERE ...
```
Isso foi aplicado tanto na tabela de resumo quanto na tabela analítica.
A vantagem é direta: em vez de o AppServer controlar milhares de pequenas inserções, o banco executa uma operação set-based, muito mais eficiente para grandes volumes.
## Atenção ao R_E_C_N_O_
Um detalhe importante em Protheus: nem toda tabela temporária criada dessa forma terá `R_E_C_N_O_` autoincremental no banco.
Durante os testes, isso ficou evidente com violação de chave primária, pois os registros estavam sendo inseridos com `R_E_C_N_O_ = 0`.
A solução foi gerar o recno diretamente no `SELECT`, usando uma composição baseada em:
```sql
MAX(R_E_C_N_O_) + ROW_NUMBER()
```
Assim, cada carga direta já grava a temporária com chave válida, sem depender de autoincremento inexistente.
Esse ponto é essencial em otimizações Protheus com tabela física temporária: não basta fazer `INSERT INTO ... SELECT`; é preciso respeitar a estrutura que o DBAccess espera.
## Empresa e filial: cuidado obrigatório
Outro ponto importante é que tabelas Protheus são físicas por grupo de empresas.
Por isso, o processamento normal de um relatório continua respeitando empresa e filial em iterações separadas.
No entanto, quando a chamada vem de um documento já posicionado, como um pedido ou orçamento, o contexto é diferente. O usuário não está solicitando uma apuração ampla; ele quer a expectativa daquele documento específico.
Nesse caso, não faz sentido:
- abrir perguntas;
- iniciar processamento em job;
- percorrer todas as empresas e filiais;
- recalcular um universo maior que o documento corrente.
A solução foi criar um modo de processamento por documento.
Quando a rotina recebe o tipo do documento e o `RecNo()`, ela processa apenas a empresa e filial correntes, chamando a função de cálculo diretamente.
Sem job, sem varredura geral e sem interface de parâmetros.
## Resultado técnico
A otimização trouxe ganhos em três frentes:
1. **Performance**
O processamento pesado foi empurrado para o banco, reduzindo loops, buscas repetidas e inclusões linha a linha.
2. **Manutenção**
A regra principal ficou concentrada em um único ponto, evitando duplicação entre relatório, consulta e expectativa de comissão.
3. **Segurança funcional**
O fluxo normal do relatório continua respeitando o processamento por empresa e filial. Já o fluxo vindo de um pedido ou orçamento usa somente o documento corrente.
## Lições aprendidas
Nem toda otimização em Protheus é sobre trocar índice, criar tabelas novas ou ajustar uma query isolada.
Às vezes, o maior ganho vem de mudar o desenho da rotina:
- sair do pensamento registro a registro;
- usar SQL para operações em lote;
- preservar o contexto empresa/filial;
- centralizar regra de negócio;
- tratar corretamente `R_E_C_N_O_`;
- separar claramente relatório, consulta e expectativa de documento.
Customização boa não é apenas a que funciona. É a que funciona bem com volume, respeita a arquitetura do Protheus e continua fácil de manter depois.
---
#DNATech #Protheus #TOTVS #AdvPL #TLPP #SQLServer #Performance #ERP #Customizacao #DBAccess
Comentários
Postar um comentário