[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