Fórum Melhorar Performance #529895

26/08/2015

0

Galera eu estou fazendo um Procedure no Firebird 2.5 para Sugestão de Compra de Produtos, mas esta muito demorado (30seg), já criei os índices. Tem como melhorar essa performance?


CREATE OR ALTER PROCEDURE SP_PRODUTOS_MOV (
    dt_ini date,
    dt_fim date,
    compra_para integer,
    prazo_entrega integer,
    perc_variacao numeric(5,2))
returns (
    prod_id integer,
    prod_ean varchar(14),
    prod_descricao varchar(120),
    prod_und_com varchar(6),
    prod_valor_compra numeric(18,2),
    prod_valor_venda numeric(18,2),
    qtde_caixa numeric(5,2),
    for_id integer,
    for_nome_fantasia varchar(80),
    qtde_entrada numeric(5,2),
    mes_entrada varchar(200),
    qtde_vendida numeric(5,2),
    mes_venda varchar(200),
    media_vendida numeric(5,2),
    qtde_dias integer,
    est_min numeric(5,2),
    estoque numeric(5,2),
    consumo_esperado numeric(5,2),
    variacao_esperado numeric(5,2),
    sugestao numeric(5,2),
    sugestao_cxa numeric(5,2))
as
BEGIN
  FOR
    select 
        produtos.prod_id,
        produtos.prod_ean,
        produtos.prod_descricao,
        produtos.prod_und_com,
        coalesce(produtos.prod_valor_compra,0),
        coalesce(produtos.prod_valor_venda,0),
        coalesce(PRODUTOS.prod_estoq_min,0),
        coalesce(produtos.qtde_caixa,0),
        produtos.for_id,
        fornecedor.for_nome_fantasia
    from produtos
       inner join fornecedor on (produtos.for_id = fornecedor.for_id)
    order by  produtos.for_id, produtos.prod_descricao
    INTO :PROD_ID,
         :PROD_EAN,
         :PROD_DESCRICAO,
         :PROD_UND_COM,
         :PROD_VALOR_COMPRA,
         :PROD_VALOR_VENDA,
         :EST_MIN,
         :qtde_caixa,
         :FOR_ID,
         :FOR_NOME_FANTASIA

  DO


  FOR
    select
        coalesce(sum(compras_itens.icp_qtde),0) as qtde
    from compras_itens
       inner join compras on (compras_itens.com_id = compras.com_id)
    where
      cast(compras.COM_DATA_COMPRA as date) between :dt_ini and :dt_fim  and
      compras_itens.prod_id = :prod_id
   INTO:qtde_entrada

  DO



  FOR
    select  list('['|| iif(CHAR_LENGTH(COM_DATA_COMPRA) = 1, '0'|| COM_DATA_COMPRA,COM_DATA_COMPRA) || ' - Qt: ' || cast(qtde as integer)||']',' | ')  from(
        select
            extract(month FROM compras.COM_DATA_COMPRA) as COM_DATA_COMPRA,
            coalesce(sum(compras_itens.icp_qtde),0) as qtde
        from compras_itens
           inner join compras on (compras_itens.com_id = compras.com_id)
        where
          cast(compras.COM_DATA_COMPRA as date) between :dt_ini and :dt_fim  and
        
          compras_itens.prod_id = :prod_id
        GROUP BY
          extract(month FROM compras.COM_DATA_COMPRA) )
     INTO:mes_entrada

  DO





  FOR
    select
        coalesce(sum(pedidos_itens.pi_qtde),0)
    from pedidos
       inner join pedidos_itens on (pedidos.ped_id = pedidos_itens.ped_id)
    where
      cast(pedidos.data_emissao as date) between :dt_ini and :dt_fim  and
      pedidos.status  = 1  and
      pedidos_itens.prod_id = :prod_id  and
      pedidos.tipo_id < 6
    INTO :qtde_vendida
  DO

  FOR
    select  list('['|| iif(CHAR_LENGTH(data_emissao) = 1, '0'|| data_emissao,data_emissao) || ' - Qt: ' || cast(qtde as integer)||']',' | ')  from(
        select
            extract(month FROM pedidos.data_emissao) as data_emissao,
            coalesce(sum(pedidos_itens.pi_qtde),0) as qtde
        from pedidos_itens
            inner join pedidos on (pedidos_itens.ped_id = pedidos.ped_id)
        where
            cast(pedidos.data_emissao as date) between :dt_ini and :dt_fim  and
            pedidos.status  = 1  and
            pedidos_itens.prod_id = :prod_id  and
            pedidos.tipo_id < 6
        GROUP BY
            extract(month FROM pedidos.data_emissao) )
    INTO:MES_VENDA
  DO


  FOR
    select IIF(COALESCE(SUM(qtde),0) > 0, COALESCE(SUM(qtde),0) / COALESCE(COUNT(data_emissao),0),0)  from(
        select
            extract(month FROM pedidos.data_emissao) as data_emissao,
            coalesce(sum(pedidos_itens.pi_qtde),0) as qtde
        from pedidos_itens
           inner join pedidos on (pedidos_itens.ped_id = pedidos.ped_id)
        where
          cast(pedidos.data_emissao as date) between :dt_ini and :dt_fim  and
          pedidos.status  = 1  and
          pedidos_itens.prod_id = :prod_id  and
          pedidos.tipo_id < 6
        GROUP BY
          extract(month FROM pedidos.data_emissao) )
    INTO :MEDIA_VENDIDA
  DO


  FOR
    SELECT SUM(estoq_atual) FROM SP_GET_ESTOQUE_LOJAS(:prod_id)
    INTO:ESTOQUE
  DO


  BEGIN
    qtde_dias = datediff (day from :dt_ini to  :dt_fim);
    consumo_esperado = coalesce((MEDIA_VENDIDA / 30),0) * (coalesce(:compra_para,0) + coalesce(:prazo_entrega,0));
    variacao_esperado =  (consumo_esperado * coalesce(:perc_variacao,0)) / 100;
    sugestao  = (consumo_esperado + variacao_esperado + (est_min - estoque));
    sugestao_cxa  = sugestao * qtde_caixa;
    SUSPEND;
  END
END
Sidney Abreu

Sidney Abreu

Responder

Posts

01/09/2015

Fabio Basso

Olá Sidney,

Sua procedure está executando 7 selects. Quando você faz esses selects separadamente o retorno está sendo rápido (menos de 1 segundo)? Qual é a configuração do equipamento e qual é a quantidade de registros que estão sendo processados? Se você tiver uma base de dados de testes eu executaria isso em outro equipamento para compararmos o resultado.
Responder

Gostei + 0

01/09/2015

Sidney Abreu

9 seg
Responder

Gostei + 0

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

Aceitar