[firebase-br] Extrema Lentidão em Consulta Firebird 5
Rodrigo Gomes da Silva
rodrgomes em gmail.com
Sábado Maio 17 00:31:12 -03 2025
Aqui fizemos o sistema inteiro inicialmente somente com firebird,
trabalhando com bancos grandes , com todo ele com sentenças otimizadas pra
ficar bom no firebird. Quando trocamos para postgresql, algumas sentenças
ficavam mais lentas e tivemos de adaptar para ficar bom em ambos.
Eu não chamaria banco de 5gb grande, são os pequenos nossos.. os grandes
tem mais de 100gb, porem hoje a maioria já são PG, porem não por
performance... sempre tivemos bancos desse tamanho em FB.
Eu peguei o dump q você colocou la e remontei o 1o sql... demorava muitos
minutos com a query padrão, e agora no PG ainda é mais rapido, porem no FB
ta demorando 3s aqui no meu computador, e dando o mesmo resultado da sua
original
select
SUB1.MERCADORIA,
GP.Descricao,
SUB1.Codigo,
SUB1.Saldo_Tipo,
sum(Rel.Quant) AS Saldo_Total
from (
SELECT CAD.MERCADORIA, CAD.Codigo, E.SALDO_TIPO
FROM (
SELECT REL.Cod_Mercadoria,
SUM(CASE WHEN
(REL.Lixo <> 'S' OR REL.Lixo IS NULL OR REL.Lixo = '') AND
(REL.Arquivo <> 'S' OR REL.Arquivo IS NULL OR REL.Arquivo = '') AND
(REL.data_emissao >= '01.12.2024')
THEN REL.Quant ELSE NULL END ) AS Saldo_Tipo
FROM ESTOQUE REL
group by REL.Cod_Mercadoria
) E
RIGHT JOIN CADASTRO_MERCADORIAS CAD ON CAD.Codigo = E.Cod_Mercadoria
) SUB1
LEFT JOIN ESTOQUE REL ON REL.Cod_Mercadoria = SUB1.Codigo
LEFT JOIN CADASTRO_PRECOS GP ON GP.Cod_Produto = REL.Cod_Mercadoria AND
GP.ID_Preco = REL.ID_Preco AND (GP.INATIVO IS NULL OR GP.INATIVO = '' OR
GP.INATIVO = 'N')
GROUP BY
SUB1.MERCADORIA,
GP.Descricao,
GP.id_Preco,
SUB1.Codigo,
SUB1.Saldo_Tipo
On Fri, May 16, 2025 at 9:13 PM Luciano franca <luapfirebird em yahoo.com.br>
wrote:
> Interesse dizer que no seu caso o firebird é mais rápido que o postgresql.
>
> Aqui no meu sistema tenho 180 relatórios e em todos eles o postgresql
> ganha e não é por pouca coisa não, geralmente é coisas do tipo 10 segundos
> contra 3 minutos.
>
> O caso mais absurdo é esse do estoque.
>
> Porém veja esses casos todos são em bancos grandes porque os pequenos são
> todos firebird.
>
> Porém passou de 5gb já faço migração para postgresql.
>
> Quer ver diferença é "window functions" ai o postgresql é um foguete
> comparado ao firebird.
> Em 16 de mai. de 2025, 18:27 -0300, Rodrigo Gomes da Silva <
> rodrgomes em gmail.com>, escreveu:
>
> Sentença ruim pacas... coloque uma sentença valida que é mais facil de
> analisar...
>
> Aonde trabalho nos usamos firebird e postgresql. O sistema era feito
> somente com firebird, e passamos a converter ele para funcionar nos 2
> sistemas. Bancos com dados de 1gb a 300gb (1 deles tem 3tb mas é de
> arquivos binários). Diversas sentenças rodavam mais rapidas no firebird que
> tiveram de ser alteradas para rodar melhor no postgresql, aonde o mesmo
> banco convertido do firebird ficava bem mais lento, e o contrário é
> verdadeiro tb.
>
> Cada banco tem suas particularidades, e uma do postgresql é que é dificil
> medir tempo individual de sentença pois ele faz algum tipo de cache de
> resultados aonde uma sentença pode demorar, mas se vc tentar rodar ela
> denovo vai rapido pq o PG fez algum cache não dos dados, e sim de algo
> relacionado com o resultado ou filtro.
>
> Por tudo que ja tivemos de problema com lentidão de sentença, a sua de
> exemplo basico vai ficar lenta mesmo, pq esta multiplicando o numero de
> registros da 1a com o da 2a...
>
> Olhando a sua sentenca do 1o post, uma coisa que pode ser q deixe ela
> lenta é que o firebird pode estar processando os 2 with todos registros de
> estoque que vc ta agrupando... você pode resolver isso fazendo uma subquery
> 1o depois fazer a contagem da quantidade... tenta mantendo o mesmos with
> (soma_estoque_1 e cadastro_preco) e use o select principal como
>
> SELECT SUB.MERCADORIA, SUB.Descricao, SUB.Codigo, SUB.Saldo_Tipo,
> SUM(REL.Quant) as Saldo_Total
> FROM
> (SELECT
> CAD.MERCADORIA,
> GP.Descricao,
> CAD.Codigo,
> ST1.Saldo_Tipo
> FROM
> CADASTRO_MERCADORIAS CAD
> LEFT JOIN CADASTRO_PESSOAS CF ON CF.Codigo = CAD.cod_fornecedor
> LEFT JOIN CADASTRO_PRECO GP ON GP.Cod_Produto = REL.Cod_Mercadoria AND
> GP.ID_Preco = REL.ID_Preco
> LEFT JOIN Soma_Estoque_1 ST1 ON ST1.Cod_Mercadoria = REL.Cod_Mercadoria
> ) SUB
> LEFT JOIN ESTOQUE REL ON REL.Cod_Mercadoria = SUB.Codigo
> GROUP BY
> SUB.MERCADORIA,
> SUB.Descricao,
> SUB.Codigo,
> SUB.Saldo_Tipo
>
>
> Fiz no bloco de notas, então poderia ter algum erro ai, mas a ideia deve
> ter dado para perceber...
>
> On Fri, May 16, 2025 at 5:39 PM Luciano franca <luapfirebird em yahoo.com.br>
> wrote:
>
>> Eu Fiz apenas um exemplo basico onde dois "LEFT Join" causam extrema
>> lentidão no Firebird meu SQL completo.
>> Veja esse topico para entender melhor
>>
>> https://github.com/FirebirdSQL/firebird/issues/8568
>>
>>
>>
>>
>>
>>
>> Em sexta-feira, 16 de maio de 2025 às 15:48:49 BRT, Rodrigo Gomes da
>> Silva <rodrgomes em gmail.com> escreveu:
>>
>>
>> SELECT
>> CM.Codigo,
>> CM.MERCADORIA,
>> Sum(E.quant) As Saldo,
>> AVG(E2.preco_custo) As Preco
>> FROM CADASTRO_MERCADORIAS CM
>> left Join ESTOQUE E ON (E.Cod_Mercadoria = CM.codigo)
>> left Join ESTOQUE E2 ON ( E2.Cod_Mercadoria = CM.Codigo )
>> Group By 1, 2
>>
>> Você quer o preço medio e a quantidade, por que esta fazendo 2 joins para
>> o mesmo filtro? Os registros são multiplicados.
>>
>> SELECT
>> CM.Codigo,
>> CM.MERCADORIA,
>> Sum(E.quant) As Saldo,
>> AVG(E.preco_custo) As Preco
>>
>> FROM CADASTRO_MERCADORIAS CM
>> left Join ESTOQUE E ON (E.Cod_Mercadoria = CM.codigo)
>> Group By 1, 2
>>
>>
>> Aparentemente bastaria fazer isso.
>>
>
Mais detalhes sobre a lista de discussão lista