none
Ajuda com Tunning de Query RRS feed

  • Pergunta

  • Bom dia meu amigos,

    eu sei que oque eu vou perguntar é muito vago, mas, caso necessitem de mais informações me comuniquem q na medida do possível eu informo.

    Eu tenho um cenário que eu preciso fazer varreduras em tabelas de vendas,produtos,NF e etc... para montar um consolidado de relatório fiscal.

    São muitas linhas a serem retornadas e cálculos a serem feitos para retornar os valores devidamente formatados

    E um agravante é que se trata de uma base de um ERP, então não tenho muita autonomia para mexer nas estruturas das tabelas.

    Alguém saberia me ajudar em alguma forma de melhorar ainda mais performance desta query que retorna aproximadamente 4 Milhões de registros e hoje leva 00:01:10?

    obrigado.

    QUERY

    	
    	SELECT  CONCAT(SUBSTRING( D2_EMISSAO , 7 , 2), '/', SUBSTRING( D2_EMISSAO , 5 , 2), '/', SUBSTRING( D2_EMISSAO , 1 , 4))  AS   DATA  , 
    	SF2.F2_XPEDHTK  AS  PEDHTK    , SF2.F2_DOC   NF             ,  SF2.F2_CLIENTE  AS CLIENTE  ,   
    	SD2.D2_COD      AS COD      , 
    	SD2.D2_QUANT    AS QTD      ,  SD2.D2_PRCVEN  AS PRECOUNID  ,  SD2.D2_TOTAL     AS VALOR    , 
    	SD2.D2_VALFRE   AS FRETE    , ( CASE WHEN SF4.F4_DUPLIC = 'S' and SF4.F4_CODIGO <> '505' THEN  SD2.D2_TOTAL   ELSE 0 END ) AS VALFAT   , 
    	( CASE WHEN SF4.F4_DUPLIC = 'S' and SF4.F4_CODIGO <> '505' THEN  SD2.D2_TOTAL  + SD2.D2_VALFRE    ELSE 0 END ) AS VALORNF   , 
    	SD2.D2_VALIMP6 - ROUND( ((SD2.D2_VALFRE * D2_ALQIMP6 )/100 ) , 2 )  AS PIS_MER    , 
    	SD2.D2_VALIMP5 - ROUND( ((SD2.D2_VALFRE * D2_ALQIMP5 )/100 ) , 2 )  AS COFINS_MER ,
    	SD2.D2_VALICM  - ( CASE WHEN SD2.D2_VALICM = 0 THEN 0 ELSE (ROUND( ((SD2.D2_VALFRE * D2_PICM   )/100 )  , 2 ) ) END ) AS IMCS_MER   , 
    	(SD2.D2_VALIMP6 - ROUND( ((SD2.D2_VALFRE * D2_ALQIMP6 )/100 ) , 2 ) + 
    	SD2.D2_VALIMP5 - ROUND( ((SD2.D2_VALFRE * D2_ALQIMP5 )/100 ) , 2 ) +
    	SD2.D2_VALICM  - ( CASE WHEN SD2.D2_VALICM = 0 THEN 0 ELSE (ROUND( ((SD2.D2_VALFRE * D2_PICM   )/100 )  , 2 ) ) end ) )  AS  IMP_MER   , 
    	ROUND( ((SD2.D2_VALFRE * D2_ALQIMP6 )/100 ) , 2 ) AS PIS_FRE    , 
    	ROUND( ((SD2.D2_VALFRE * D2_ALQIMP5 )/100 ) , 2 ) AS COFINS_FRE ,
    	( CASE WHEN SD2.D2_VALICM = 0 THEN 0 ELSE ( ROUND( ((SD2.D2_VALFRE * D2_PICM   )/100 ) , 2 ) ) end )AS ICMS_FRE    , 
    	(ROUND( ((SD2.D2_VALFRE * D2_ALQIMP6 )/100 ) , 2 )  + 
    	ROUND( ((SD2.D2_VALFRE * D2_ALQIMP5 )/100 ) , 2 )  + 
    	( CASE WHEN SD2.D2_VALICM = 0 THEN 0 ELSE ( ROUND( ((SD2.D2_VALFRE * D2_PICM   )/100 ) , 2 )  ) end ) ) AS IMP_FRE    , 
    	SD2.D2_VALIMP6 AS PIS_TT    , 
    	SD2.D2_VALIMP5 AS COFINS_TT ,
    	SD2.D2_VALICM  AS IMCS_TT   , 
    	SD2.D2_VALIMP6  + SD2.D2_VALIMP5 + SD2.D2_VALICM  AS IMP_TT   , 
        ( CASE WHEN SF4.F4_DUPLIC = 'S' and SF4.F4_CODIGO <> '505' THEN  
    	    SD2.D2_TOTAL   
    	-  ( SD2.D2_VALIMP6 - ROUND( ((SD2.D2_VALFRE * D2_ALQIMP6 )/100 ) , 2 ) ) 
    	-  ( SD2.D2_VALIMP5 - ROUND( ((SD2.D2_VALFRE * D2_ALQIMP5 )/100 ) , 2 )  ) 
    	-  ( SD2.D2_VALICM  - ( CASE WHEN SD2.D2_VALICM = 0 THEN 0 ELSE (ROUND( ((SD2.D2_VALFRE * D2_PICM   )/100 )  , 2 )  ) end ))
    	 ELSE 0 END )  AS  VDALIQ  , 
    	SD2.D2_CUSTO1   AS CUSTO  , 
    	ROUND( (( CASE WHEN SF4.F4_DUPLIC = 'S' and SF4.F4_CODIGO <> '505' 
    	THEN  ( SD2.D2_TOTAL    
    	-  ( SD2.D2_VALIMP6 - ROUND( ((SD2.D2_VALFRE * D2_ALQIMP6 )/100 ) , 2 ) ) 
    	-  ( SD2.D2_VALIMP5 - ROUND( ((SD2.D2_VALFRE * D2_ALQIMP5 )/100 ) , 2 )  ) 
    	-  ( SD2.D2_VALICM  - ( CASE WHEN SD2.D2_VALICM = 0 THEN 0 ELSE ( ROUND( ((SD2.D2_VALFRE * D2_PICM   )/100 )  , 2 )  ) end )) 
    	-  SD2.D2_CUSTO1 )  ELSE 0 END )  / (SD2.D2_TOTAL  
    	-  ( SD2.D2_VALIMP6 - ROUND( ((SD2.D2_VALFRE * D2_ALQIMP6 )/100 ) , 2 ) ) 
    	-  ( SD2.D2_VALIMP5 - ROUND( ((SD2.D2_VALFRE * D2_ALQIMP5 )/100 ) , 2 )  ) 
    	-  ( SD2.D2_VALICM  - ( CASE WHEN SD2.D2_VALICM = 0 THEN 0 ELSE ( ROUND( ((SD2.D2_VALFRE * D2_PICM   )/100 )  , 2 )  ) end ) ))) , 2 )  AS GP , 
    	0 AS  FALTA , 
    	HTKVENDAS  ,  
    	ORIGEM  ,   
    	PED.HORAPE  AS  HORA  ,
    	 concat(SUBSTRING( PED.DT_EMISSA , 7 , 2), '/', SUBSTRING(PED.DT_EMISSA , 5 , 2), '/', SUBSTRING( PED.DT_EMISSA , 1 , 4))    AS DAT_PEDIDO  , 
    	SF2.F2_HORA   AS HORA_NF	,
    	0         AS CUS_LENS  
    	FROM SF2010  SF2 (NOLOCK)  
    	INNER JOIN SD2010 SD2 (NOLOCK)  ON ( SF2.F2_DOC          = SD2.D2_DOC  AND  SF2.F2_SERIE     =    SD2.D2_SERIE  ) 
    	INNER JOIN SF4010 SF4 (NOLOCK)  ON ( SD2.D2_TES          = SF4.F4_CODIGO  ) 
    	INNER JOIN  HTK_LISTA_PEDIDOS PED (NOLOCK)  ON ( SF2.F2_XPEDHTK    = PED.PEDHTK ) 
    	WHERE  SF2.F2_FILIAL   = '01' 
    	AND    SD2.D2_FILIAL   = '01' 
    	AND    SF4.F4_FILIAL   = '01' 
    	AND    SF2.D_E_L_E_T_ = ' ' 
    	AND    SD2.D_E_L_E_T_ = ' ' 
    	AND    SF4.F4_ESTOQUE = 'S' 
    	AND    SF4.D_E_L_E_T_ = ' ' 



    sexta-feira, 1 de novembro de 2019 13:23

Todas as Respostas

  • LINK PARA O XML DO PLANO DE EXECUÇÃO (ENORME)

    justpaste.it/4lch9


    sexta-feira, 1 de novembro de 2019 13:32
  • Deleted
    sexta-feira, 1 de novembro de 2019 14:23

  • Jose, boa tarde!
    Muito obrigado por responder....

    As minhas configurações estão marcadas para auto update e auto create statistics,

    Também já mandei atualizar todas as estatísticas com o comando "sp_updatestats" e o plano de execução continua o mesmo.

    Também tentei utilizar o tuning advisor que não propôs nenhuma melhoria.

    Tem alguma outra dica ?

    sexta-feira, 1 de novembro de 2019 17:13
  • Deleted
    sexta-feira, 1 de novembro de 2019 21:53
  • Eliakin,

    Mesmo fazendo uso da System Stored Procedure sua tabela não foi atualizada, provavelmente significa que alguma estatística criada para esta tabela poderá estar apresentando um histograma desatualizado.

    Recomendo identificarmos as estatísticas criadas para esta tabela, vamos utilizar este Código de exemplo:

    Select OBJECT_NAME(a.object_id) AS Objeto, a.name, a.auto_created From sys.stats a Where OBJECT_NAME(a.object_id) = 'SD2010' 
    Go

    Com base no resultado do select acima, você terá a relação de estatísticas pertencentes a esta tabela, nosso próximo passo será tentar forçar que o SQL Server avalie no nível mais profunda cada estatística identificada, vamos então fazer uso do comando Update Statistics em conjunto com a opção FullScan:

    UPDATE STATISTICS SD2010 (digite aqui o nome da estatística) WITH FULLSCAN;  
    Depois de atualizar cada estatística da tabela SD2010, veja se o plano de execução apresenta alguma mudança, principalmente valores retornados pela linhas estimadas e executadas.



    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    sexta-feira, 1 de novembro de 2019 22:56
  • Deleted
    • Sugerido como Resposta IgorFKModerator segunda-feira, 2 de dezembro de 2019 17:45
    segunda-feira, 4 de novembro de 2019 23:13