Fórum Preciso trocar and exists por left join #459864

30/10/2013

0

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

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

Geison

Responder

Posts

30/10/2013

Thiago Irrazabal

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.

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.
Responder

Gostei + 0

30/10/2013

Alex Lekao

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.

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
Responder

Gostei + 0

30/10/2013

Thiago Irrazabal

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.
Responder

Gostei + 0

30/10/2013

Alex Lekao

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
Responder

Gostei + 0

31/10/2013

Geison

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.

Responder

Gostei + 0

11/11/2013

Geison

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.
Responder

Gostei + 0

12/11/2013

Alex Lekao

OI Geison, bom dia!!

Obrigado pelo retorno.

Abraco.
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar