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 Atilio (Daniel Atilio)
Especialista em Engenharia de Software pela FIB. Entusiasta de soluções Open Source. E blogueiro nas horas vagas.

10 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.

Deixe uma resposta