Você sabia que o MsSeek é mais performático que o DbSeek em AdvPL?

Descobri isso recentemente e eu não fazia ideia.

Estava conversando algumas semanas atrás com meu amigo Wallace Freitas (LinkedIn), e ele havia me falado que o DbSeek e MsSeek haviam diferenças, sendo que o segundo era mais performático.

Eu confesso que não sabia dessa informação e fui pesquisar, até que encontrei o link no TDN que fala sobre isso – https://tdn.totvs.com/display/framework/Desempenho+DbSeek+x+MsSeek

Baseado no exemplo do TDN, eu montei o exemplo abaixo:

#Include "TOTVS.ch"

Static nVezes := 10000

/*/{Protheus.doc} User Function zSeek
Funcao para comparar desempenho entre DbSeek e MSSeek
@type  Function
@author Atilio
@since 27/06/2020
@version version
@example
    u_zSeek()
@see https://tdn.totvs.com/display/framework/Desempenho+DbSeek+x+MsSeek
/*/

User Function zSeek()
    Local aArea := GetArea()

    //Teste com DbSeek
    fTestDB()

    //Teste com MsSeek
    fTestMS()

    RestArea(aArea)
Return

Static Function fTestDB()
    Local nAtual
    Local cHoraIni := Time()
    Local cHoraFin
    Local cDifer

    //Abrindo a tabela de Clientes e posicionando no topo
    DbSelectArea("SA1")
    SA1->(DbSetOrder(1))
    SA1->(DbGoTop())

    //Percorre o número de vezes e atualiza a hora final ao sair do laco
    For nAtual := 1 To nVezes
        SA1->(DbSeek(FWxFilial("SA1") + "000001" + "01" ))
    Next
    cHoraFin := Time()

    //Mostra mensagem ao usuario
    cDifer := ElapTime(cHoraIni, cHoraFin)
    MsgInfo("DbSeek:" + CRLF + "Hora Inicio: " + cHoraIni + CRLF + "Hora Final: " + cHoraFin + CRLF + "Total: " + cDifer, "Atencao")
Return

Static Function fTestMS()
    Local nAtual
    Local cHoraIni := Time()
    Local cHoraFin
    Local cDifer

    //Abrindo a tabela de Clientes e posicionando no topo
    DbSelectArea("SA1")
    SA1->(DbSetOrder(1))
    SA1->(DbGoTop())

    //Percorre o número de vezes e atualiza a hora final ao sair do laco
    For nAtual := 1 To nVezes
        SA1->(MsSeek(FWxFilial("SA1") + "000001" + "01" ))
    Next
    cHoraFin := Time()

    //Mostra mensagem ao usuario
    cDifer := ElapTime(cHoraIni, cHoraFin)
    MsgInfo("MsSeek:" + CRLF + "Hora Inicio: " + cHoraIni + CRLF + "Hora Final: " + cHoraFin + CRLF + "Total: " + cDifer, "Atencao")
Return

E realmente o MsSeek é mais rápido que o DbSeek. Fazendo a mesma operação 10.000 vezes (de procurar um registro na SA1), o MsSeek demorou 4 segundos (média de 250 seeks por segundo), enquanto o DbSeek demorou 16 segundos (média de 62,5 seeks por segundo). Confira o print abaixo de resultado (a esquerda DbSeek e a direita MsSeek).

Comparação entre MsSeek e DbSeek

Bom pessoal, por hoje é só.

Abraços e até a próxima.

Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

14 Responses

  1. Sulivan Simões disse:

    Dica importantíssima, principalmente quando tem que dar uma melhorada na performance daquela rotina que você vê, e a principio não tem muita coisa a se fazer.

  2. Patini disse:

    muito boa a dica, um camarada da TOTVS havia me falado isso também….

  3. Wallace disse:

    Fala Daniel beleza?

    Cara é um prazer poder estar contribuindo com o T.I.

    Como sempre seus artigos bem detalhados e explicativos.

    Excelente trabalho.

    Abraços

  4. Alexandre Behling disse:

    Deve ter algum cuidado ao usar o MsSeek? Ele é indicado para quando procura só um mesmo registro varias vezes ou quando trocamos de registro também? Obrigado pelo seu conteúdo.

    • Dan_Atilio disse:

      Eu que agradeço pelo comentário.
      Respondendo a dúvida, o cuidado são os mesmos do DbSeek, como por exemplo, usar a referência antes.
      No contexto explicado no link do TDN e no exemplo demonstrado no artigo, são quando o mesmo registro é processado várias vezes, ideal para rotinas que trabalhem com contabilidade ou estrutura de produtos onde pode ter inúmeros posicionamentos em vários ou no mesmo registro.
      O ideal mesmo, é se possível fazer uma query para manipular os dados, mas entre o DbSeek e o MsSeek, o segundo é mais performático por buscar os dados em memória, caso o registro já tenha sido posicionado anteriormente.

  5. PEDROSO disse:

    Show, hein…
    Bora alterar 4376 ocorrências do dbseek.

  6. Henrique Sciascio disse:

    Bom dia Daniel, tudo bem?

    Muito interessante a dinâmica de explicação e uma dica muito valiosa.

    Só queria tirar uma duvida, devo tomar algum cuidado ao preferir utilizar o MSseek do que o DbSeek, por exemplo, caso na tabela não esteja posicionado no registro ou algo assim?

    Agradeço desde já a atenção!

  7. Luccas disse:

    Boa tarde Daniel, tudo joia?

    Excelente trabalho que você tem feito compartilhando seus conhecimentos.

    Em relação as MsSeek ele mantém em memória os dados isso não pode causar mais consumo de memoria em relação ao DbSeek?

    Agradeço desde já a atenção!

    • Bom dia Luccas, tudo joia graças a Deus e você?

      Opa, primeiramente obrigado pelo feedback, é muita bondade e generosidade sua.

      Agora quanto a utilização do MsSeek ou do DbSeek, nos clientes que atendo, eu me faço algumas perguntas como:
      a. Essa função vai ficar um bom tempo em memória? (tipo vai ser uma outras ações numa tela padrão, ou uma dialog customizada)
      b. Ou ela vai ser uma rotina com início, meio e fim como um processamento ou relatório colocada direto no menu?
      c. Os usuários utilizam o SIGAADV ou o SIGAMDI? (o segundo cada aba é uma thread, então ao fechar uma, a memória em teoria é liberada)
      d. A estrutura do servidor do cliente na aplicação (AppServer) como é de Memória RAM? E a estrutura do banco de dados como é de processamento e leitura de disco?
      e. Quantos dados serão processados em estimativa atual e para os próximos meses?

      Ai dependendo das respostas acima eu escolho entre usar o DbSeek ou MsSeek, pois por exemplo, mesmo que o MsSeek mantenha mais memória numa thread, assim que a thread encerrar já libera. Agora imagina que a estrutura do cliente onde ta o banco de dados, não tem SSD ou não tem um processamento legal, imagina ficar dando vários DbSeek para encontrar os dados, como que fica o IO de disco.

      Então, tudo depende do cenário em que você vai atender, mas cabe sempre antes alinhar com o cliente explicando os prós e contras de ambos, pois pode ser que mesmo que você queira desenvolver usando por exemplo DbSeek, ai o cliente te fala que estão migrando para o cloud ou comprando mais equipamento para ter mais memória RAM e que você pode usar o MsSeek para não ter muito IO no SQL.

      Tenha uma ótima e abençoada quarta feira.

      Um grande abraço.

Deixe uma resposta

Terminal de Informação