[firebase-br] Extrema Lentidão em Consulta Firebird 5
Rodrigo Gomes da Silva
rodrgomes em gmail.com
Sábado Maio 17 11:40:19 -03 2025
Isso não é um problema no firebird, e o prb não é os 2 left join... no seu
caso é que o 2o join que le toda tabela pra dar o sum, é executado toda vez
q corre um registro de estoque, para depois agrupar...
Por exemplo , digamos que estoque tem 100.000 registros, de 1000 materiais.
Para cada 1 dos 100.000 registros ele faz a soma de um material, por
100.000 vezes ao inves de fazer somente pra 1000 que seria 1 pra cada
material.
Não é um erro, pois é como ele funciona, e não esta errado, pode ser
evitado melhorando o sql. O postgresql faz otimizações diferentes e por
isso fica rapido, mas isso é questão da engine totalmente diferente.
O ticket que você mostrou deixa claro isso... o cara que colocou o link la
referencia a um ticket que ta marcado como "type: improvement" (não bug) e
vai ser recurso novo do firebird 6 que deve sair em 2026
On Sat, May 17, 2025 at 8:29 AM Luciano franca via lista <
lista em firebase.com.br> wrote:
> Ótimo comando SQL de fato ele resolve meu problema e fico muito grato.
> porém conforme pode ver nesse post existe um problema no Firebird que está
> no Rodmap da versão 6 para ser corrigido
> https://github.com/FirebirdSQL/firebird/issues/8568
>
>
>
>
>
> Em sexta-feira, 16 de maio de 2025 às 10:34:06 BRT, Rogério <
> rbleonel em yahoo.com.br> escreveu:
>
>
> 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.PrecoFROM
> CADASTRO_MERCADORIAS CMLEFT JOIN SaldoEstoque SE ON SE.Cod_Mercadoria =
> CM.CodigoLEFT 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
>
>
> ______________________________________________
> 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