O principal motivo da lentidão é o uso de concatenação de campos (||) e funções (como trim) nas cláusulas WHERE e JOIN. Isso impede o Firebird de usar índices, forçando o banco a ler registro por registro (Natural Scan).
Aqui estão os passos para resolver:
## 1. Pare de concatenar no JOIN e no WHERE
Em vez de b.docum||b.codfor... = '"+xchave+"', você deve passar os valores individualmente para cada coluna. O Firebird 2.5 não consegue otimizar uma string concatenada contra um índice composto.
## 2. Use "Conditional Aggregation" (Soma Condicional)
Em vez de fazer 4 sub-selects na mesma tabela, você faz uma única varredura e separa os valores usando CASE WHEN. Isso reduz drasticamente o I/O do disco.
## 3. Exemplo de Query Otimizada
Assumindo que você possa passar os valores da chave separados no seu código:
Código: Selecionar todos
SELECT
b.valor,
b.dc,
b.nrecibo,
d.valor,
-- Agrupamento das somas em uma única leitura
SUM(CASE WHEN b.dc = 'C' AND (b.nrecibo IS NULL OR TRIM(b.nrecibo) = '') THEN b.valor ELSE 0 END) as soma_c_vazio,
SUM(CASE WHEN b.dc = 'D' AND (b.nrecibo IS NULL OR TRIM(b.nrecibo) = '') THEN b.valor ELSE 0 END) as soma_d_vazio,
SUM(CASE WHEN b.dc = 'C' AND (b.nrecibo <> '') THEN b.valor ELSE 0 END) as soma_c_cheio,
SUM(CASE WHEN b.dc = 'D' AND (b.nrecibo <> '') THEN b.valor ELSE 0 END) as soma_d_cheio
FROM PAGARB bINNER JOIN PAGARD d ON
d.docum = :docum AND d.codfor = :codfor AND d.tpnota = :tpnota AND d.serie = :serie AND d.ordem = :order
WHERE
b.docum = :docum AND b.codfor = :codfor AND b.tpnota = :tpnota AND b.serie = :serie AND b.ordem = :ordem
GROUP BY 1, 2, 3, 4
## Por que isso fica mais rápido?
1. SARGability: Ao usar coluna = :valor, o Firebird usa o índice da chave primária ou estrangeira.
2. Menos leituras: Os sub-selects originais faziam o banco "correr" a tabela PAGARB várias vezes. Com o CASE WHEN, ele lê uma vez só.
3. Índice Composto: Se você ainda não tem, crie um índice nas tabelas PAGARB e PAGARD contendo as colunas (DOCUM, CODFOR, TPNOTA, SERIE, ORDEM).
Dica extra: No Firebird 2.5, evite TRIM dentro do WHERE se possível. Se o campo nrecibo puder ser gravado apenas como vazio ou preenchido (sem espaços extras), a comparação direta b.nrecibo = '' é mais veloz.
Você tem um índice composto criado com esses campos exatos ou eles são índices individuais?