[firebase-br] Extrema Lentidão em Consulta Firebird 5

Rogério rbleonel em yahoo.com.br
Sexta Maio 16 10:35:47 -03 2025


A lentidão da sua SELECT pode ser causada por alguns fatores combinados, especialmente relacionados ao uso incorreto ou ineficiente de JOINs com agregações (SUM, AVG).

Join duplicado e efeito de cartesian join não intencional. Você está fazendo dois LEFT JOINs na mesma tabela (ESTOQUE), mas com aliases diferentes (E e E2), ambos ligados a CADASTRO_MERCADORIAS.

left Join ESTOQUE E  ON (E.Cod_Mercadoria  = CM.codigo)
left Join ESTOQUE E2 ON (E2.Cod_Mercadoria = CM.Codigo)

Isso causa uma multiplicação do número de linhas retornadas antes da agregação (GROUP BY), pois:

Se para uma mercadoria há 10 registros na tabela ESTOQUE, o primeiro join (E) retorna 10.

O segundo join (E2) repete isso, resultando em 10 x 10 = 100 linhas, afetando os valores de SUM e AVG, e deixando a consulta absurdamente lenta.

A melhor forma de resolver isso é fazer as agregações separadamente e depois unir o resultado via JOIN:

WITH SaldoEstoque AS (
  SELECT Cod_Mercadoria, SUM(quant) AS Saldo
  FROM ESTOQUE
  GROUP BY Cod_Mercadoria
),
PrecoEstoque AS (
  SELECT Cod_Mercadoria, AVG(preco_custo) AS Preco
  FROM ESTOQUE
  GROUP BY Cod_Mercadoria
)

SELECT
  CM.Codigo,
  CM.MERCADORIA,
  SE.Saldo,
  PE.Preco
FROM CADASTRO_MERCADORIAS CM
LEFT JOIN SaldoEstoque SE ON SE.Cod_Mercadoria = CM.Codigo
LEFT JOIN PrecoEstoque PE ON PE.Cod_Mercadoria = CM.Codigo


Conectado 16/05/2025 10:19:24, Luciano franca via lista <lista em firebase.com.br> escreveu:
para conhecimento dos amigo esse meu Post é de fato uma limitação do Firebird

veja meu post 
https://github.com/FirebirdSQL/firebird/issues/8568
Extremely slow to do "Left Join" on the same table · Issue #8568 · FirebirdSQL/firebird

|
|
|
| | |

|

|
|
| |
Extremely slow to do "Left Join" on the same table · Issue #8568 · Fireb...

This command below takes 40 minutes SELECT CM.Codigo, CM.MERCADORIA, Sum(E.quant) As Saldo, AVG(E2.preco_custo) ...
|

|

|




Em quinta-feira, 15 de maio de 2025 às 11:32:54 BRT, Luciano franca via lista escreveu:

Sim eu sei disso mais veja esse Select simples que postei, e como disse faz 3 anos que tenho esse problema e já tentei de tudo e não consigo otimizar,   basta usar dois "LEFT JOIN" na mesma tabela para o Firebird ficar horrível,   testei Postgres, MySQL e SQLServer e todos são rápidos

Acho que isso seja um bug no otimizador do Firebird  se puder baixar o banco que postei no link e ver você mesmo são apenas 2 tabelas faça o teste para ver
https://mega.nz/file/k6gUhBpJ#4gXE7oLSW_DJdKB9UZaMUQvsI9GOPiYYJ8wqciHUVdw



    Em quinta-feira, 15 de maio de 2025 às 11:17:06 BRT, Carlos H. Cantu via lista escreveu: 

Lfvl> sim são muitos registros,  banco do cliente tem mais 5 GB de tamanho, 
Lfvl> esse é o motivo que quando o cliente reclama eu tenho que trocar o
Lfvl> Firebird por Postgres  sempre depois de uns 4 gb o Firebird não aguenta

Tenho bancos com dezenas de gigabytes, e há bancos por aí com centenas de GB (e
até terabytes). O problema não deve ser o Firebird, mas o SQL que vc está
usando.

Cada SGBD tem seu próprio otimizador. É preciso entender os conceitos e
limitações deles para escrever selects otimizados extraindo todo o potencial.

[]s
Carlos H. Cantu
eBook Guia de Migração para o FB 5 - www.firebase.com.br/guiafb5.php
www.FireBase.com.br - www.firebirdnews.org - blog.firebase.com.br

Lfvl>  não posso fazer "Select" usando a tabela Estoque no "From"  como Principal tem que ser o "Cadastro" 

Lfvl> Primeiro "Cadastro"  porque pode ter produto que não tem estoque e eu
Lfvl> preciso que esses produtos sejam mostrados,

Lfvl> sim são muitos registros,  banco do cliente tem mais 5 GB de tamanho, 
Lfvl> esse é o motivo que quando o cliente reclama eu tenho que trocar o
Lfvl> Firebird por Postgres  sempre depois de uns 4 gb o Firebird não aguenta
Lfvl>    Em quinta-feira, 15 de maio de 2025 às 10:54:34 BRT, edenilso.mga---
Lfvl> via lista escreveu: 
Lfvl> 
Lfvl>  Bom dia Amigo,

Lfvl> Fiz a restauração do seu backup aqui,

Lfvl> na tabela ESTOQUE criei um índice para o campo Cod_Mercadoria, já melhorou,

Lfvl> mas seu select com left na mesma tabela 2x está retornando milhões de
Lfvl> registros.

Lfvl> Invertendo as tabelas rodou instantaneamente ...

Lfvl>  SELECT CM.Codigo, CM.MERCADORIA
Lfvl>     FROM estoque e
Lfvl>     left Join cadastro_mercadorias cm
Lfvl>       ON (E.Cod_Mercadoria = CM.codigo)
Lfvl>     left Join cadastro_mercadorias cm2
Lfvl>       ON (E.Cod_Mercadoria = CM2.Codigo )

Lfvl> Dá uma revisado no seu select.

Lfvl> Abraço



Lfvl> Em qui., 15 de mai. de 2025 às 10:31, Luciano franca via lista <
Lfvl> lista em firebase.com.br> escreveu:

>>  Tanto o Backup do Banco como os comando DDL do banco estão no link abaixo:
>>
>> https://mega.nz/file/k6gUhBpJ#4gXE7oLSW_DJdKB9UZaMUQvsI9GOPiYYJ8wqciHUVdw
>>
>>
>>
>>    Em quinta-feira, 15 de maio de 2025 às 10:22:59 BRT,
>> mauricio.zottis--- via lista escreveu:
>>
>>  Bom dia.
>> Poste a estrutura d(DDL) dessas tabelas
>>
>> Em 15/05/2025 10:11, Luciano franca via lista escreveu:
>>
>> > novo link permanente no Mega
>> >
>> https://mega.nz/file/k6gUhBpJ#4gXE7oLSW_DJdKB9UZaMUQvsI9GOPiYYJ8wqciHUVdw
>> >
>> > Esse problema eu já tenho a mais de 3 anos e nunca consegui resolver a
>> > minha solução atualmente é muito complexa pois envolve eu colocar o
>> > Postges nos cliente que reclamam de lentidão  eu não gosto do Postgres
>> > só coloco ele em ultimo caso.
>> > Eu continuo achando que se trata de um Bug no Firebird
>> > Se puder dar uma analisada nesse banco só tem duas tabelas com o
>> > simples select abaixo
>> > SELECT CM.Codigo, CM.MERCADORIA 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
>> >
>> > Em quinta-feira, 15 de maio de 2025 às 09:59:10 BRT, Luciano franca via
>> > lista escreveu:
>> >
>> > Eu não entendi o que você quiz dizer com  "+0 ou || "
>> > veja esse link onde tem o backup do Banco feito em Firebird 3  e também
>> > os comandos SQL caso quero criar o banco já com os
>> > Dadoshttps://
>> mega.nz/file/8uYwiBoK#y3PdspfXLOSc6wGS1c4i6vHFHCXAzgqfAvX_rY2ZGMM
>> > Esse problema eu já tenho a mais de 3 anos e nunca consegui resolver a
>> > minha solução atualmente é muito complexa pois envolve eu colocar o
>> > Postges nos cliente que reclamam de lentidão  eu não gosto do Postgres
>> > só coloco ele em ultimo caso.
>> > Eu continuo achando que se trata de um Bug no Firebird
>> > Se puder dar uma analisada nesse banco só tem duas tabelas com o
>> > simples select abaixo
>> > SELECT CM.Codigo, CM.MERCADORIA 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
>> >
>> > Em quinta-feira, 15 de maio de 2025 às 09:41:34 BRT, Carlos H. Cantu
>> > via lista escreveu:
>> >
>> > Com LEFT é a mesma coisa, PLAN e tempo continuam bons:
>> >
>> > Query
>> > ------------------------------------------------
>> > select emissao, pn.codprod , pn2.codprod
>> > from notas n
>> > left join prodnota pn on pn.id_num = n.id_num
>> > left join prodnota pn2 on pn2.id_num = n.id_num
>> > where n.emissao > date '1.10.2024'
>> >
>> > Plan
>> > ------------------------------------------------
>> > PLAN JOIN (JOIN (N INDEX (IDX_VENDAS_EMISSAO), PN INDEX
>> > (FK_PRODNOTA_NOTAFISCAL)), PN2 INDEX (FK_PRODNOTA_NOTAFISCAL))
>> >
>> > Query Time
>> > ------------------------------------------------
>> > Prepare      : 0,00 ms
>> > Execute      : 141,00 ms
>> > Avg fetch time: 0,01 ms
>> >
>> > []s
>> > Carlos H. Cantu
>> > eBook Guia de Migração para o FB 5 - www.firebase.com.br/guiafb5.php
>> > [1]
>> > www.FireBase.com.br [2] - www.firebirdnews.org [3] -
>> > blog.firebase.com.br
>> >
>> > Lf>  O colega não usou "LEFT" não posso usar "INNER" eu não entendi o
>> > que você quiz dizer com  "+0 ou || "
>> >
>> > Lf> veja esse link onde tem o backup do Banco feito em Firebird 3  e
>> > também os
>> > Lf> comandos SQL caso quero criar o banco já com os Dados
>> > Lf> 6.5 MB file on MEGA
>> >
>> > Lf> Esse problema eu já tenho a mais de 3 anos e nunca consegui
>> > resolver a
>> > Lf> minha solução atualmente é muito complexa pois envolve eu colocar o
>> > Postges
>> > Lf> nos cliente que reclamam de lentidão  eu não gosto do Postgres só
>> > coloco ele em ultimo caso.
>> >
>> > Lf> Eu continuo achando que se trata de um Bug no Firebird
>> >
>> > Lf> Se puder dar uma analisada nesse banco só tem duas tabelas com o
>> > simples select abaixo
>> >
>> > Lf>  SELECT CM.Codigo, CM.MERCADORIA FROM CADASTRO_MERCADORIAS CM left
>> > Join
>> > Lf> ESTOQUE E ON (E.Cod_Mercadoria = CM.codigo) left Join ESTOQUE E2 ON
>> > (
>> > Lf> E2.Cod_Mercadoria = CM.Codigo ) Group By 1, 2
>> >
>> > Lf> |
>> > Lf> |
>> > Lf> |
>> > Lf> |  |  |
>> >
>> > Lf>  |
>> >
>> > Lf>  |
>> > Lf> |
>> > Lf> |  |
>> > Lf> 6.5 MB file on MEGA
>> >
>> > Lf>  |
>> >
>> > Lf>  |
>> >
>> > Lf>  |
>> >
>> > Lf>    Em quinta-feira, 15 de maio de 2025 às 08:54:50 BRT, Carlos H.
>> > Cantu escreveu:
>> > Lf>
>> > Lf>  O fato de mencionar a mesma tabela em mais de um join, por si só,
>> > não é o
>> > Lf> problema, desde que o PLAN mostre que um índice apropriado está
>> > sendo usado em
>> > Lf> ambas as buscas.
>> >
>> > Lf> No seu caso, ao tirar o segundo join, provavelmente está fazendo
>> > com que o PLAN
>> > Lf> mude e fique mais eficiente. Vc vai ter que ir testando alterando
>> > as ordens dos
>> > Lf> joins, usando +0 ou || '' em algumas junções, para tentar fazer com
>> > que o
>> > Lf> Firebird escolha um plano mais eficiente.
>> >
>> > Lf> Veja abaixo, o tempo foi muito rapido mesmo com 2 joins na mesma
>> > tabela. O PLAN
>> > Lf> está eficiente:
>> >
>> > Lf> Query
>> > Lf> ------------------------------------------------
>> > Lf> select emissao, pn.codprod, pn2.codprod
>> > Lf> from notas n
>> > Lf> join prodnota pn on pn.id_num = n.id_num
>> > Lf> join prodnota pn2 on pn2.id_num = n.id_num -- Repetindo o JOIN
>> > where n.emissao >> date '1.10.2024'
>> >
>> > Lf> Plan
>> > Lf> ------------------------------------------------
>> > Lf> PLAN JOIN (N INDEX (IDX_VENDAS_EMISSAO), PN INDEX
>> > (FK_PRODNOTA_NOTAFISCAL), PN2 INDEX (FK_PRODNOTA_NOTAFISCAL))
>> >
>> > Lf> Query Time
>> > Lf> ------------------------------------------------
>> > Lf> Prepare      : 0,00 ms
>> > Lf> Execute      : 187,00 ms
>> > Lf> Avg fetch time: 0,02 ms
>> >
>> > Lf> Query
>> > Lf> ------------------------------------------------
>> > Lf> select emissao, pn.codprod
>> > Lf> from notas n
>> > Lf> join prodnota pn on pn.id_num = n.id_num -- APENAS 1 JOIN
>> > where n.emissao >> date '1.10.2024'
>> >
>> > Lf> Plan
>> > Lf> ------------------------------------------------
>> > Lf> PLAN JOIN (N INDEX (IDX_VENDAS_EMISSAO), PN INDEX
>> > (FK_PRODNOTA_NOTAFISCAL))
>> >
>> > Lf> Query Time
>> > Lf> ------------------------------------------------
>> > Lf> Prepare      : 0,00 ms
>> > Lf> Execute      : 62,00 ms
>> > Lf> Avg fetch time: 0,01 ms
>> >
>> > Lf> []s
>> > Lf> Carlos H. Cantu
>> > Lf> eBook Guia de Migração para o FB 5 -
>> > www.firebase.com.br/guiafb5.php [1]
>> > Lf> www.FireBase.com.br [2] - www.firebirdnews.org [3] -
>> > blog.firebase.com.br
>> >
>> > Lfvl>>  não pode ser "INNER" tem que ser "LEFT"  eu coloquei 2 no caso
>> > mais
>> > Lfvl>> simples porém tem alguns caso onde tenho até 4 "JOINS" na mesma
>> > tabela o
>> > Lfvl>> problema é que isso no Postgres roda em segundos como coloquei
>> > no 1 email
>> > Lfvl>> 15 segundos contra 30 minutos do Firebird
>> >
>> > Lfvl>> Eu estou achando que isso é um bug no Firebird.
>> > Lfvl>>    Em quinta-feira, 15 de maio de 2025 às 08:19:17 BRT, Armando
>> > Boza
>> > Lfvl>> Gonçalves via lista escreveu:
>> > Lfvl>>
>> > Lfvl>>  Bom dia, 2 LEFT JOIN para a mesma tabela?
>> >
>> > Lfvl>> Eu já tive problemas de desempenho com left join e acabei
>> > resolvendo com
>> > Lfvl>> UNION, separei os selects e ficou bem rápido.
>> >
>> > Lfvl>> Faz um teste.
>> >
>> > Lfvl>> Em 15/05/2025 07:09, Luciano franca via lista escreveu:
>> > Acredito que encontrei o problema e não sei como resolver mesmo sem CTE
>> > não adianta
>> > basta acessar a mesma tabela duas vezes para o Firebird se perder
>> > se fizer algo simples como isso já vai dar problemas veja
>> >
>> > Select
>> > Cp.codigo, Cp.nome
>> > From cadastro_pessoas cp
>> > left join venda v on (v.cod_cliente = cp.codigo) Left join venda v2 on
>> > (v2.cod_cliente = cp.codigo)  se eu comentar essa segunda junção é
>> > excecutado em 1 segundo
>> > Group by 1, 2
>>


______________________________________________
FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
Para saber como gerenciar/excluir seu cadastro na lista, use: http://www.firebase.com.br/fb/artigo.php?id=1107
Para consultar mensagens antigas: http://www.firebase.com.br/pesquisa_lista.html
 
______________________________________________
FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
Para saber como gerenciar/excluir seu cadastro na lista, use: http://www.firebase.com.br/fb/artigo.php?id=1107
Para consultar mensagens antigas: http://www.firebase.com.br/pesquisa_lista.html

______________________________________________
FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
Para saber como gerenciar/excluir seu cadastro na lista, use: http://www.firebase.com.br/fb/artigo.php?id=1107
Para consultar mensagens antigas: http://www.firebase.com.br/pesquisa_lista.html


Mais detalhes sobre a lista de discussão lista