Duvida Duvida cache do client progress

Discussão em 'Progress 4GL' iniciado por jaozi_nho, Fevereiro 3, 2014.

  1. jaozi_nho

    jaozi_nho Membro Participativo

    Olá amigos do mundo progress, tenho uma duvida e ao mesmo tempo uma dica valiosa para compartilhar para quem tiver tendo os mesmos problemas que eu .

    Recentemente andei tendo diversos problemas de perfomance em relatorios com grande volumes de dados e relacionamento e percebi que o client do progress não faz nenhum cache interno sobre os find e for each com varios each, first subsequentes, como no exemplo abaixo .

    FOR EACH nota-fiscal NO-LOCK WHERE
    nota-fiscal.dt-emis-nota >= DATE("01/01/2014") AND
    nota-fiscal.dt-cancela = ? ,
    FIRST emitente NO-LOCK OF nota-fiscal
    :
    END.

    Rodando essa query no banco de um cliente que faturou 100 mil notas no mes de janeiro até hoje ele irá ler as mesmas 100 mil vezes a tabela emitente, mesmo que o cliente tenha faturado notas apenas para poucos clientes diferentes em todas as notas, trocar o first da logica da query (FOR) por um find first dentro do loop do for each tem exatamente a mesma perfomance e tempo de execução e leituras de bancos, como no exemplo abaixo .

    FOR EACH nota-fiscal NO-LOCK WHERE
    nota-fiscal.dt-emis-nota >= DATE("01/01/2014") AND
    nota-fiscal.dt-cancela = ?
    :
    FIND FIRST emitente NO-LOCK WHERE
    emitente.cod-emitente = nota-fiscal.cod-emitente
    .
    END.

    Como o cliente tem apenas 2000 clientes cadastrados no banco, e somente poucos deles estão ativos executar a query fazendo o dump de ambas as tabelas é muito mais rapido do que relacionar as mesmas, lembrando que utilizando as logicas acima ele le da tabela emitente 100 mil registros, sendo que a tabela só possui 2000 registros .

    Uma maneira de otimizar a perfomance das leituras e relacionamentos encontradas por mim, porem não a mais ideial foi fazer um cache utilizando temp-tables, assim melhorando muito a perfomance e consumo dos bancos (leitura), em alguns casos em até 100 vezes, como podem ver a seguir .

    DEF TEMP-TABLE tt-emitente NO-UNDO
    FIELD cod-emitente LIKE emitente.cod-emitente
    FIELD nome-abrev LIKE emitente.nome-abrev
    FIELD endereco LIKE emitente.endereco
    FIELD bairro LIKE emitente.bairro
    INDEX idx AS UNIQUE PRIMARY cod-emitente
    .

    FOR EACH nota-fiscal NO-LOCK WHERE
    nota-fiscal.dt-emis-nota >= DATE("01/01/2014") AND
    nota-fiscal.dt-cancela = ?
    :
    FIND tt-emitente NO-LOCK WHERE
    tt-emitente.cod-emitente = nota-fiscal.cod-emitente
    NO-ERROR .
    IF NOT AVAIL tt-emitente THEN DO:
    FIND emitente NO-LOCK WHERE
    emitente.cod-emitente = nota-fiscal.cod-emitente
    .
    CREATE tt-emitente .
    BUFFER-COPY emitente TO tt-emitente .
    END.
    END.

    Com a utilização da temp-table como cache o programa rodou em 4x menos tempo, e leu do banco de dados apenas 300 e poucos registros da tabela emitente, claro que tal otimização já deveria ser realizada pelo próprio client do progress e aliviando um pouco o lado do programador, porem isso não acontece, temos diversos casos aonde tal logica melhora em muito a perfomance, como por exemplo qualquer tabela e cadastro que faça referencia com alguma tabela de movimento, com a tabela "item" .

    A minha duvida é, existe alguma forma melhor de obter perfomance nesses casos? Lembrando que esse foi apenas um exemplo e esse não causa grande impacto, porem já trabalhei com relatorios que levavam mais de 10 horas de execução devido a problemas como esse, aonde tal solução reduziu o tempo para 30 minutos devido aos constantes acessos repetidos ao banco .

    Agradeço o tempo e estou aberto para debate e sugestões .

    Abraço .
  2. Agnaldo

    Agnaldo Membro Ativo

    Você pode usar o mesmo raciocínio, mas ao invés de usar uma temp-table, que usa disco, usar uma work-table, que usa apenas memória.
  3. fdantas

    fdantas Administrator Moderador

    Boa Tarde jaozi_nho ,

    No caso como são mais notas que clientes, tente inverter o For each

    PHP:
    for each emitente ,
    EACH nota-fiscal  ....
  4. jaozi_nho

    jaozi_nho Membro Participativo

    Mais Agnaldo work-table não é mais utilizado, segundo os manuais é recomendável não utilizar mais work-table em situação nenhuma, e sim sempre temp-table, agora não sei dizer quais sao as mudanças de uma para outra .
  5. jaozi_nho

    jaozi_nho Membro Participativo

    Olá, agradeço a sugestão, nesse caso ele irá ler sempre toda a tabela emitente, no caso 2000 registros, vou testar para verificar .
  6. Agnaldo

    Agnaldo Membro Ativo

    Desculpe, ma para essas situações de performance, ainda é a melhor opção, visto que os dados estão todos em RAM.
    É claro, se você não sabe os limites dos dados (quantidade), aí não é indicado.
    brazjuniorgyn curtiu isso.

Compartilhe esta Página