none
Performance com Where RRS feed

  • Pergunta

  • Pessoal

        Onde eu teria melhor performance de execução do script abaixo :

    Opção 1)
    	update tb_rec set
    	tb_rec.ds_status = 'L'
    	,tb_rec.baixado = getdate()
    	,tb_rec.id_Bordero = @id_Bordero
    	from nc_receber tb_rec inner join tbl_Transacao_Forma tb_for
    	on tb_rec.ChaveControle = tb_for.id_Chave_Controle 
    	where tb_for.id_Transacao_Pagar = @id_Transacao_Bordero
    
    
    Opção 2)
    	update tb_rec set
    	tb_rec.ds_status = 'L'
    	,tb_rec.baixado = getdate()
    	,tb_rec.id_Bordero = @id_Bordero
    	from nc_receber tb_rec inner join tbl_Transacao_Forma tb_for
    	on tb_rec.ChaveControle = tb_for.id_Chave_Controle 
    and tb_for.id_Transacao_Pagar = @id_Transacao_Bordero
    

    sexta-feira, 15 de novembro de 2013 12:33

Respostas

  • Deleted
    sexta-feira, 15 de novembro de 2013 13:50
  • Deleted
    segunda-feira, 30 de dezembro de 2013 00:14
  • Junior

       E na sua opinião entre os 2 script qual seria o melhor ?

    Opção 2.1)
    	update tb_rec set
    	tb_rec.ds_status = 'L'
    	,tb_rec.baixado = getdate()
    	,tb_rec.id_Bordero = @id_Bordero
    	from nc_receber tb_rec inner join tbl_Transacao_Forma tb_for
    	on tb_rec.ChaveControle = tb_for.id_Chave_Controle 
    	where tb_for.id_Transacao_Pagar = @id_Transacao_Bordero
    
    Opção 2.2)
    update tb_rec 
      set tb_rec.ds_status = 'L'
         ,tb_rec.baixado = getdate()
         ,tb_rec.id_Bordero = @id_Bordero
      from nc_receber 
      where ChaveControle = 
              (select id_Chave_Controle from tbl_Transacao_Forma where id_Transacao_Pagar = @id_Transacao) 

    Nei,

    Complementando a informação do Junior, sua opção 2.1 é a melhor pela condição de processamento do comando UPDATE dentro do SQL Server.

    Como referência, veja a documentação oficial do SQL Server para este comando (http://technet.microsoft.com/pt-br/library/ms177523.aspx#TableHints ) em especial à parte sobre Table Hint e o comando SELECT http://technet.microsoft.com/pt-br/library/ms189499.aspx ) onde à ordem de processamento lógico afeta a resolução e a performance da consulta, e consequentemente, afeta também os comandos DELETE e UPDATE da mesma forma. Segue abaixo a ordem de processamento lógico de uma instrução T-SQL:


    1. FROM
    2. ON
    3. JOIN
    4. WHERE
    5. GROUP BY
    6. WITH CUBE OU WITH ROLLUP
    7. HAVING
    8. SELECT
    9. DISTINCT
    10. ORDER BY
    11. TOP

    Com este conceito, podemos afirmar que é possível obter o resultado desejado de performance através de condições "ON" em detrimento do "WHERE". Em alguns casos o ganho de sua consulta pode ser significativo, mas para poucos registros pode ser insignificante.

    Um modo que pode ajudar sua decisão para verificar exatamente qual comando UPDATE é mais vantajoso (de forma simples) utilize antes da instrução o comando:

    SET STATISTICS TIME ON
    GO
    SET STATISTICS IO ON
    GO
    
    update tb_rec set
    tb_rec.ds_status = 'L'
    ,tb_rec.baixado = getdate()
    ,tb_rec.id_Bordero = @id_Bordero
    from nc_receber tb_rec inner join tbl_Transacao_Forma tb_for
    on tb_rec.ChaveControle = tb_for.id_Chave_Controle 
    where tb_for.id_Transacao_Pagar = @id_Transacao_Bordero
    
    SET STATISTICS TIME OFF
    GO
    SET STATISTICS IO OFF
    GO

    Espero que seja útil para você.

    Abraços,

    Durval Ramos
    Microsoft Partner | MTA - SQL Server 2012
    ----------------------------------
    Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"
    segunda-feira, 23 de dezembro de 2013 18:09
    Moderador

Todas as Respostas

  • Deleted
    sexta-feira, 15 de novembro de 2013 13:50
  • Nei,

    Identificar o melhor solução é algo que pode variar muito inclusive no mesmo cenário.

    Eu particularmente gosto da segunda opção, ao meu ver ela é mais claro e legível, onde temos o From com as tabelas envolvidas e relacionadas e a clausula where como filtro para os nossos dados.

    Você poderia compartilhar conosco a sua estrutura do seu ambiente?

    A sugestão do José Diz para você consultar o Livro do Inside é fantástica, inclusive eu mesmo tenho este livro e faço uso do mesmo.


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]

    sexta-feira, 22 de novembro de 2013 16:47
  • Junior

        A estrutura é +/- esta abaixo, veja se ajuda na sua analise :

        E a opção que você falou que seria melhor seria esta mesmo ?

    -- código 2
    update tb_rec
     
    set tb_rec.ds_status = 'L'
        
    ,tb_rec.baixado = getdate()
        
    ,tb_rec.id_Bordero = @id_Bordero
     
    from nc_receber
      where ChaveControle =
              (select id_Chave_Controle from tbl_Transacao_Forma where id_Transacao_Pagar = @id_Transacao


    CREATE TABLE [dbo].[tbl_Transacao_Forma](
     [id_Transacao_Pagar] [int] NOT NULL,
     [id_Chave_Controle] [int] NOT NULL,
     [id_Tipo_Pagto] [int] NOT NULL,
     [id_Forma_Pagto] [int] NOT NULL,
     [id_Banco] [int] NOT NULL,
     [nr_Documento] [char](10) NOT NULL,
     [nr_Seq_Documento] [int] NOT NULL,
     [dt_Vencto_Documento] [datetime] NOT NULL,
     [vl_Documento] [decimal](18, 2) NOT NULL
    ) ON [PRIMARY]
    
     
    
    CREATE TABLE [dbo].[nC_RECEBER](
            [ChaveControle] [int] IDENTITY(1,1) NOT NULL, 
            [referencia] [char](20) NOT NULL,
     [cadastro] [datetime] NULL,
     [sacadoprincipal] [int] NOT NULL,
     [vencimento] [datetime] NOT NULL,
     [valor] [decimal](18, 2) NOT NULL,
     [status] [char](1) NOT NULL,
     [codlancamento] [int] NULL,
     [vendas] [int] NULL,
     [operador] [int] NULL,
     [statusdocaixa] [int] NULL,
     [codvenda] [int] NULL,
     [baixado] [datetime] NULL,
     [nf] [char](9) NULL,
     [fatura] [char](12) NULL,
     [banco] [int] NOT NULL,
     [boleto] [char](20) NULL,
     [empresa] [int]  NOT NULL,
     [id_Bordero]  [int]  NOT NULL
    ) ON [PRIMARY]
    

    sexta-feira, 22 de novembro de 2013 22:43
  • Neibala,

    Na minha opinião sim, mais isso tem que ser analisado, mas um fator importante é o uso da clausula where para filtrar os dados, bem como, se as colunas declaradas no Where forem índices.


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]

    sexta-feira, 22 de novembro de 2013 22:47
  • Junior

       E na sua opinião entre os 2 script qual seria o melhor ?

    Opção 2.1)
    	update tb_rec set
    	tb_rec.ds_status = 'L'
    	,tb_rec.baixado = getdate()
    	,tb_rec.id_Bordero = @id_Bordero
    	from nc_receber tb_rec inner join tbl_Transacao_Forma tb_for
    	on tb_rec.ChaveControle = tb_for.id_Chave_Controle 
    	where tb_for.id_Transacao_Pagar = @id_Transacao_Bordero
    
    Opção 2.2)
    update tb_rec 
      set tb_rec.ds_status = 'L'
         ,tb_rec.baixado = getdate()
         ,tb_rec.id_Bordero = @id_Bordero
      from nc_receber 
      where ChaveControle = 
              (select id_Chave_Controle from tbl_Transacao_Forma where id_Transacao_Pagar = @id_Transacao) 
    

    sexta-feira, 22 de novembro de 2013 22:56
  • Neibala,

    Cara eu prefiro a opção 1.

    Não gosto muito de ficar utilizar Subquery.


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]

    sexta-feira, 29 de novembro de 2013 15:34
  • Junior

       E na sua opinião entre os 2 script qual seria o melhor ?

    Opção 2.1)
    	update tb_rec set
    	tb_rec.ds_status = 'L'
    	,tb_rec.baixado = getdate()
    	,tb_rec.id_Bordero = @id_Bordero
    	from nc_receber tb_rec inner join tbl_Transacao_Forma tb_for
    	on tb_rec.ChaveControle = tb_for.id_Chave_Controle 
    	where tb_for.id_Transacao_Pagar = @id_Transacao_Bordero
    
    Opção 2.2)
    update tb_rec 
      set tb_rec.ds_status = 'L'
         ,tb_rec.baixado = getdate()
         ,tb_rec.id_Bordero = @id_Bordero
      from nc_receber 
      where ChaveControle = 
              (select id_Chave_Controle from tbl_Transacao_Forma where id_Transacao_Pagar = @id_Transacao) 

    Nei,

    Complementando a informação do Junior, sua opção 2.1 é a melhor pela condição de processamento do comando UPDATE dentro do SQL Server.

    Como referência, veja a documentação oficial do SQL Server para este comando (http://technet.microsoft.com/pt-br/library/ms177523.aspx#TableHints ) em especial à parte sobre Table Hint e o comando SELECT http://technet.microsoft.com/pt-br/library/ms189499.aspx ) onde à ordem de processamento lógico afeta a resolução e a performance da consulta, e consequentemente, afeta também os comandos DELETE e UPDATE da mesma forma. Segue abaixo a ordem de processamento lógico de uma instrução T-SQL:


    1. FROM
    2. ON
    3. JOIN
    4. WHERE
    5. GROUP BY
    6. WITH CUBE OU WITH ROLLUP
    7. HAVING
    8. SELECT
    9. DISTINCT
    10. ORDER BY
    11. TOP

    Com este conceito, podemos afirmar que é possível obter o resultado desejado de performance através de condições "ON" em detrimento do "WHERE". Em alguns casos o ganho de sua consulta pode ser significativo, mas para poucos registros pode ser insignificante.

    Um modo que pode ajudar sua decisão para verificar exatamente qual comando UPDATE é mais vantajoso (de forma simples) utilize antes da instrução o comando:

    SET STATISTICS TIME ON
    GO
    SET STATISTICS IO ON
    GO
    
    update tb_rec set
    tb_rec.ds_status = 'L'
    ,tb_rec.baixado = getdate()
    ,tb_rec.id_Bordero = @id_Bordero
    from nc_receber tb_rec inner join tbl_Transacao_Forma tb_for
    on tb_rec.ChaveControle = tb_for.id_Chave_Controle 
    where tb_for.id_Transacao_Pagar = @id_Transacao_Bordero
    
    SET STATISTICS TIME OFF
    GO
    SET STATISTICS IO OFF
    GO

    Espero que seja útil para você.

    Abraços,

    Durval Ramos
    Microsoft Partner | MTA - SQL Server 2012
    ----------------------------------
    Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"
    segunda-feira, 23 de dezembro de 2013 18:09
    Moderador
  • Amigo, sem dúvidas a opção 1.

    Na opção 2, em algum momento a sua consulta vai buscar todos os registo que satisfação a condição do INNER JOIN e só depois é que ele volta a fazer um novo filtro. Tudo isto quando na opção 1 ele já vai filtrando os registos à medida que entra em contacto com a tabela do INNER JOIN.

    Cumprimentos

    domingo, 29 de dezembro de 2013 09:54
  • Durval

        Legal mesmo a sua explanação sobre o assunto.

        

    domingo, 29 de dezembro de 2013 15:48
  • Deleted
    domingo, 29 de dezembro de 2013 18:57
  • José

       Desde já quero agradecer a atenção de todos neste assunto, que esta me ajudando em muito em outros aspectos, e sobre a sua dúvida segue abaixo ?

    from nc_receber tb_rec inner join tbl_Transacao_Forma tb_for
    on tb_rec.ChaveControle = tb_for.id_Chave_Controle 
    where tb_for.id_Transacao_Pagar = @id_Transacao_Bordero
    
    1) tb_rec.ChaveControle - identificador único
    2) tb_for.id_Chave_Controle - identificador que se repete mais de uma vez.
    3) tb_for.id_Transacao_Pagar -  identificador que se repete mais de uma vez.

       

    domingo, 29 de dezembro de 2013 21:54
  • Deleted
    segunda-feira, 30 de dezembro de 2013 00:14