Preciso trocar and exists por left join
Ola pessoal.
Estou fazendo a manutenção de um sistema,
que gera um relatorio de custo medio de venda.
Porem, o relatório no cliente demora 3o minutos para abrir.
Entao foi solicitado para que troque and exists por left join, isso irá melhorar a performance.
Procede essa informacao ?
Segue sql gerado pelo fonte do delphi
Estou fazendo a manutenção de um sistema,
que gera um relatorio de custo medio de venda.
Porem, o relatório no cliente demora 3o minutos para abrir.
Entao foi solicitado para que troque and exists por left join, isso irá melhorar a performance.
Procede essa informacao ?
Segue sql gerado pelo fonte do delphi
SELECT IR.CD_FILIAL, IR.CD_SERVICO, IR.CD_FILIAL,
SUM(QUANTIDADE) AS QUANTIDADE,
SUM(QUANTIDADE*(VLR_SERVICO-((VLR_SERVICO*PRC_DESCONTO)/100))) AS VLR_TOTAL,
(SUM((QUANTIDADE*(VLR_SERVICO-((VLR_SERVICO*PRC_DESCONTO)/100))))/SUM(QUANTIDADE)) AS VLR_MEDIO
FROM ITENS_OS_RECAP IR
WHERE IR.CD_NOTA IS NOT NULL
AND (FLAG_SITUACAO = 5)
AND IR.CD_FILIAL = 4
AND IR.DATA_NOTA BETWEEN '01/01/2013' AND '01/31/2013'
AND EXISTS (
SELECT NULL
FROM OS_RECAP OS
WHERE IR.CD_FILIAL = OS.CD_FILIAL
AND IR.CD_OS = OS.CD_OS
AND CD_PESSOA = '310.590.078-00'
AND CD_VENDEDOR = '386.707.989-72'
)
AND EXISTS (
SELECT NULL
FROM SERVICOS_CONSERTOS SC
WHERE IR.CD_FILIAL = SC.CD_FILIAL
AND IR.CD_SERVICO = SC.CD_SERVICO
AND ( CD_GRUPO IN ( 20112016, 19, 518, 519, 522, 541, 551, 524, 525, 523, 528, 529, 534, 532, 538, 533, 543, 550006, 535, 530, 546, 544, 531, 539, 545, 536, 537, 527, 550003, 666, 540, 550009, 20112012, 20112013, 550, 444, 89, 9, 8, 777, 778, 526, 520, 521)
)
)
GROUP BY IR.CD_FILIAL, IR.CD_SERVICO, IR.CD_FILIAL
UNION ALL
SELECT IRC.CD_FILIAL, IRC.CD_SERVICO, IR.CD_FILIAL,
SUM(IRC.QUANTIDADE) AS QUANTIDADE,
SUM((IRC.QUANTIDADE*IRC.VLR_CONSERTO)-IRC.VLR_DESCONTO) AS VLR_TOTAL,
(SUM((IRC.QUANTIDADE*IRC.VLR_CONSERTO)-IRC.VLR_DESCONTO) / SUM(IRC.QUANTIDADE)) AS VLR_MEDIO
FROM ITENS_OS_CONSERTO IRC
LEFT JOIN ITENS_OS_RECAP IR
ON IR.CD_FILIAL = IRC.CD_FILIAL
AND IR.CD_OS = IRC.CD_OS
AND IR.CD_ITEM = IRC.CD_ITEM
WHERE IR.CD_NOTA IS NOT NULL
AND (FLAG_SITUACAO = 5)
AND IRC.CD_FILIAL = 4
AND IR.DATA_NOTA BETWEEN '01/01/2013' AND '01/31/2013'
AND EXISTS
(
SELECT NULL FROM OS_RECAP OS
WHERE IR.CD_FILIAL = OS.CD_FILIAL
AND IR.CD_OS = OS.CD_OS
AND CD_PESSOA = '310.590.078-00'
AND CD_VENDEDOR = '386.707.989-72'
)
AND EXISTS (
SELECT NULL FROM SERVICOS_CONSERTOS SC
WHERE IR.CD_FILIAL = SC.CD_FILIAL
AND IR.CD_SERVICO = SC.CD_SERVICO
AND ( CD_GRUPO IN ( 20112016, 19, 518, 519, 522, 541, 551, 524, 525, 523, 528, 529, 534, 532, 538, 533, 543, 550006, 535, 530, 546, 544, 531, 539, 545, 536, 537, 527, 550003, 666, 540, 550009, 2'
Geison
Curtidas 0
Respostas
Thiago Irrazabal
30/10/2013
Boa tarde, se tu mudar para Inner ele obriga ter nas 2 tabelas talvez te ajude... talvez tenha algum erro na syntaxe pois escrevi direto aqui mas testa aí, vê se fica mais rápido, depois poste e diga se funcionou e como ficou, abraço.
Att,
Thiago Irrazabal de Oliveira.
SELECT IR.CD_FILIAL, IR.CD_SERVICO, IR.CD_FILIAL,
SUM(QUANTIDADE) AS QUANTIDADE,
SUM(QUANTIDADE*(VLR_SERVICO-((VLR_SERVICO*PRC_DESCONTO)/100))) AS VLR_TOTAL,
(SUM((QUANTIDADE*(VLR_SERVICO-((VLR_SERVICO*PRC_DESCONTO)/100))))/SUM(QUANTIDADE)) AS VLR_MEDIO
FROM ITENS_OS_RECAP IR
INNER JOIN OS_RECAP OSS
ON IR.CD_FILIAL = OSS.CD_FILIAL
AND IR.CD_OS = OSS.CD_OS
AND CD_PESSOA = '310.590.078-00'
AND CD_VENDEDOR = '386.707.989-72'
INNER JOIN SERVICOS_CONSERTOS SCC
ON IR.CD_FILIAL = SCC.CD_FILIAL
AND IR.CD_SERVICO = SCC.CD_SERVICO
AND ( CD_GRUPO IN ( 20112016, 19, 518, 519, 522, 541, 551, 524, 525, 523, 528, 529, 534, 532, 538, 533, 543, 550006, 535, 530, 546, 544, 531, 539, 545, 536, 537, 527, 550003, 666, 540, 550009, 20112012, 20112013, 550, 444, 89, 9, 8, 777, 778, 526, 520, 521))
WHERE IR.CD_NOTA IS NOT NULL
AND (FLAG_SITUACAO = 5)
AND IR.CD_FILIAL = 4
AND IR.DATA_NOTA BETWEEN '01/01/2013' AND '01/31/2013'
GROUP BY IR.CD_FILIAL, IR.CD_SERVICO, IR.CD_FILIAL
UNION ALL
SELECT IRC.CD_FILIAL, IRC.CD_SERVICO, IR.CD_FILIAL,
SUM(IRC.QUANTIDADE) AS QUANTIDADE,
SUM((IRC.QUANTIDADE*IRC.VLR_CONSERTO)-IRC.VLR_DESCONTO) AS VLR_TOTAL,
(SUM((IRC.QUANTIDADE*IRC.VLR_CONSERTO)-IRC.VLR_DESCONTO) / SUM(IRC.QUANTIDADE)) AS VLR_MEDIO
FROM ITENS_OS_CONSERTO IRC
LEFT JOIN ITENS_OS_RECAP IR
ON IR.CD_FILIAL = IRC.CD_FILIAL
AND IR.CD_OS = IRC.CD_OS
AND IR.CD_ITEM = IRC.CD_ITEM
INNER JOIN OS_RECAP OS
ON IR.CD_FILIAL = OS.CD_FILIAL
AND IR.CD_OS = OS.CD_OS
AND CD_PESSOA = '310.590.078-00'
AND CD_VENDEDOR = '386.707.989-72'
INNER JOIN SERVICOS_CONSERTOS SC
ON IR.CD_FILIAL = SC.CD_FILIAL
AND IR.CD_SERVICO = SC.CD_SERVICO
AND ( CD_GRUPO IN ( 20112016, 19, 518, 519, 522, 541, 551, 524, 525, 523, 528, 529, 534, 532, 538, 533, 543, 550006, 535, 530, 546, 544, 531, 539, 545, 536, 537, 527, 550003, 666, 540, 550009, 2'))
WHERE IR.CD_NOTA IS NOT NULL
AND (FLAG_SITUACAO = 5)
AND IRC.CD_FILIAL = 4
AND IR.DATA_NOTA BETWEEN '01/01/2013' AND '01/31/2013'
Att,
Thiago Irrazabal de Oliveira.
GOSTEI 0
Alex Lekao
30/10/2013
Oi Geison, boa tarde!!!
Entao cara, nas utilizacoes que ja fiz com o Firebird, usando Join eu percebi que o desempenho dele ficou ruim, isso ja foi ate meio controverso aqui em comentarios meus a esse respeito, mas eu evito utilizar Join qdo preciso mexer no meu banco firebird.
Mas se vc usar join, as sintaxes que estao no exists vc tera que colocar no where da condicao e fazer alguns testes para ver se funciona e se melhor a performance.
experimenta mudar os joins tbm aninhando as tabelas, nao sei se eh as expressao mais correta, mas segue exemplo.
por essa forma
nao sei se me fiz entender.
Mas eh uma sugestao.
Espero que tenha ajudado e que vc consiga resolver.
Abraco.
Alex - Lekao
Entao cara, nas utilizacoes que ja fiz com o Firebird, usando Join eu percebi que o desempenho dele ficou ruim, isso ja foi ate meio controverso aqui em comentarios meus a esse respeito, mas eu evito utilizar Join qdo preciso mexer no meu banco firebird.
Mas se vc usar join, as sintaxes que estao no exists vc tera que colocar no where da condicao e fazer alguns testes para ver se funciona e se melhor a performance.
experimenta mudar os joins tbm aninhando as tabelas, nao sei se eh as expressao mais correta, mas segue exemplo.
select cli, numero from venda left join cliente on venda.codcli = cli.codcli
por essa forma
select cli, numero from venda, cliente
nao sei se me fiz entender.
Mas eh uma sugestao.
Espero que tenha ajudado e que vc consiga resolver.
Abraco.
Alex - Lekao
GOSTEI 0
Thiago Irrazabal
30/10/2013
Respondendo para o nosso amigo aqui de cima, "Alex", eu uso joins em todos meus "select's", já analisei diversos códigos aqui da empresa onde trabalho que utilizavam o teu método e comparei com o meu, em quase todos os casos ganhei desempenho porem em alguns não era grande ganho, e em outros não melhorava em nada, não sei explicar o porque mas enfim... só para complementar teu comentário e adicionar a minha experiencia com a tua, abraço.
P.S.: GEISON, testa com join e sem join e posta para nós como ficou o desempenho, abraço.
Att,
Thiago Irrazabal de Oliveira.
P.S.: GEISON, testa com join e sem join e posta para nós como ficou o desempenho, abraço.
Att,
Thiago Irrazabal de Oliveira.
GOSTEI 0
Alex Lekao
30/10/2013
Tranquilo Thiago,
Acho que tudo que agrega eh bom, e precisando ter mente aberta e limpa para acrescentar e ponterar todos os comentarios. rsrsr
Nao sou um eximio programador de Banco de Dados, tao pouco um DBA fenomenal, rssr
na vdd sou muito pequeno ainda neste mundo, tenho muito pouco tempo para dedicar a mais aprendizado e aprofundamento.
Mas nao sei se tem a ver com a versao do banco que tenho aqui instalado, firebird 1,5, se nao me engano, e nas comparacoes que fiz usando o SQL Server, os desempenhos foram melhores no SQL Server usando Joins e no Firebird foram melhores usando o "aninhamento", se que eh assim que eh chamado, entao tenho isso na minha cabeca.
Pode ser so encanacao, mas procuro alertar para que possam testar das duas formas e escolher a melhor, que de o melhor desempenho, que acho que eh o caso.
Obrigado pela sua opniao, gostei de tela dado e agregou ao meu conhecimento.
Abraco.
Alex - Lekao
Acho que tudo que agrega eh bom, e precisando ter mente aberta e limpa para acrescentar e ponterar todos os comentarios. rsrsr
Nao sou um eximio programador de Banco de Dados, tao pouco um DBA fenomenal, rssr
na vdd sou muito pequeno ainda neste mundo, tenho muito pouco tempo para dedicar a mais aprendizado e aprofundamento.
Mas nao sei se tem a ver com a versao do banco que tenho aqui instalado, firebird 1,5, se nao me engano, e nas comparacoes que fiz usando o SQL Server, os desempenhos foram melhores no SQL Server usando Joins e no Firebird foram melhores usando o "aninhamento", se que eh assim que eh chamado, entao tenho isso na minha cabeca.
Pode ser so encanacao, mas procuro alertar para que possam testar das duas formas e escolher a melhor, que de o melhor desempenho, que acho que eh o caso.
Obrigado pela sua opniao, gostei de tela dado e agregou ao meu conhecimento.
Abraco.
Alex - Lekao
GOSTEI 0
Geison
30/10/2013
ok pessoal, vou fazer os testes por aqui...
aqui falam que perde muita performance usando o and exists
estou usando o componente rdprint. entao é feito tudo via codigo no delphi a geracao do sql...
caso os testes nao sejam satisfatorios , eu posto aqui, e ja migro para fast report essa parte do sistema.
Obrigado a todos.
aqui falam que perde muita performance usando o and exists
estou usando o componente rdprint. entao é feito tudo via codigo no delphi a geracao do sql...
caso os testes nao sejam satisfatorios , eu posto aqui, e ja migro para fast report essa parte do sistema.
Obrigado a todos.
GOSTEI 0
Geison
30/10/2013
Entao rapaziada,
foi feita a troca para left join,
porem, a performance, no firebird 2.5, foi a mesma .
O que foi percebido é que no firebird 1.5, o left join fica mais rapido, notavelmente.
Ja no firebird 2.5 tanto o left join quanto o and exists tem a mesma performance,
porem, os 2, bem mais rapidos que no firebird 1.5.
Entao, foi escolhido deixar o and exists, e trocar a versao do firebird no cliente.
Obrigado a todos pela ajuda.
foi feita a troca para left join,
porem, a performance, no firebird 2.5, foi a mesma .
O que foi percebido é que no firebird 1.5, o left join fica mais rapido, notavelmente.
Ja no firebird 2.5 tanto o left join quanto o and exists tem a mesma performance,
porem, os 2, bem mais rapidos que no firebird 1.5.
Entao, foi escolhido deixar o and exists, e trocar a versao do firebird no cliente.
Obrigado a todos pela ajuda.
GOSTEI 0
Alex Lekao
30/10/2013
OI Geison, bom dia!!
Obrigado pelo retorno.
Abraco.
Obrigado pelo retorno.
Abraco.
GOSTEI 0