Clipper On Line • Ver Tópico - Preencher rapidamente um array com todos os dados do Alias
Página 1 de 1

Preencher rapidamente um array com todos os dados do Alias

MensagemEnviado: 17 Jul 2018 11:25
por joaorenes
Bom dia, Pessoal.

Estou passando por algumas dificuldades no uso da linguagem ADVPL em relação ao preenchimento de um array com informações de um determinado alias. O problema está na lentidão da operação. Usando o alias diretamente, eu consigo listar mais de 100000 registros de forma instântanea, mas quando tento enviá-los para um array aparece a lentidão (mais de 2 min). Como a linguagem advpl, até onde eu sei, deriva do clipper, gostaria de um apoio.

Abaixo está a estrutura que uso para preencher o array:
Local aMeuArray := {}

meuAlias->(DbGotop())

While !meuAlias->(EOF())
aadd(aMeuArray ,{meuAlias->campo1,meuAlias->campo2, .F.})
meuAlias->(DbSkip())
Enddo

Dúvida: há alguma outra forma de fazer o preenchimento do array com as informações vindas do alias?

Obrigado.

Preencher rapidamente um array com todos os dados do Alias

MensagemEnviado: 17 Jul 2018 15:06
por Eric.Developer
olá,
é assim que se constrói um array dinâmico, independe da origem das informações.

Você informou que é instantâneo, incluindo a movimentação sequencial? ou seja, comentando a linha AADD..., é instantâneo?

1) Eu ia te sugerir que na abertura da tabela/alias, definir uma instrução SQL, filtrando e apenas com os campos necessários.
2) Outra sugestão é ver no ADVPL como executar uma instrução SQL que retorne em array e depois você complementa, exemplo:
aMeuArray:=TQuery():new():execute('SELECT CAMPO1, CAMPO2 FROM ESTOQUE WHERE STATUS='A'') // classe fictícia
AEVAL(aMeuArray, {|a, n|aMeuArray[n]:={a[1], a[2], .F.}}) // adicionando o 3º valor.


Desenvolvendo queries no Protheus
Tente também o fórum ADVPL

neste caso é mais importante pensar nos recursos próprios do ADVPL do que as minúsculas semelhanças com o Clipper.

joaorenes escreveu:Usando o alias diretamente, eu consigo listar mais de 100000 registros de forma instântanea, mas quando tento enviá-los para um array aparece a lentidão (mais de 2 min). Como a linguagem advpl, até onde eu sei, deriva do clipper, gostaria de um apoio.

Abaixo está a estrutura que uso para preencher o array:
Local aMeuArray := {}

meuAlias->(DbGotop())

While !meuAlias->(EOF())
aadd(aMeuArray ,{meuAlias->campo1,meuAlias->campo2, .F.})
meuAlias->(DbSkip())
Enddo

Dúvida: há alguma outra forma de fazer o preenchimento do array com as informações vindas do alias?

Preencher rapidamente um array com todos os dados do Alias

MensagemEnviado: 17 Jul 2018 15:51
por joaorenes
Obrigado pela Resposta.

Ao escrever "instantâneo", eu quis dizer que ao passar o Alias da tabela diretamente para um determinado componente do tipo browse (usei o TCBrowse), ele mostra todos os registros' da tabela imediatamente.

Sobre a minha "rotina", qualquer operação que faço para percorrer todos os registros acaba sendo lenta. Ex: o While que preenche o array.

A minha dúvida é: tem como evitar o loop e já carregar o array com os dados da tabela ?

Obs: eu entendo que existem limitações (principalmente usando o AADD, o DBeval, etc.), mas quero tentar todas as possibilidades.

Preencher rapidamente um array com todos os dados do Alias

MensagemEnviado: 17 Jul 2018 18:55
por JoséQuintas
joaorenes escreveu: ao passar o Alias da tabela diretamente para um determinado componente do tipo browse (usei o TCBrowse), ele mostra todos os registros' da tabela imediatamente.


Muito errado pensar isso.
Qual o tamanho da tela? 30 linhas? o browse vai ler no máximo 32 registros pra preencher a tela.
Já em array.... vai ter que ler o arquivo inteiro antes de apresentar alguma coisa.
Se for arquivo gigante...

qualquer operação que faço para percorrer todos os registros acaba sendo lenta


Imagino que talvez o browse seja lento, apesar de mostrar instantâneo, e por isso quer agilizar.
Pois é... a lentidão é pra ler registros.

Preencher rapidamente um array com todos os dados do Alias

MensagemEnviado: 18 Jul 2018 08:23
por joaorenes
Bom dia, JoséQuintas.

Obrigado pela resposta.

Faz sentido o que você acabou de expor. O problema é que os usuários estão acostumados com esse comportamento "instantâneo" e um dos requisitos que tenho que seguir é a "velocidade de execução".

Vou explicar melhor o fluxo da minha aplicação para que vocês possam ter uma ideia mais próxima da minha realidade.

1. Inicialmente, tenho que ir em uma determinada tabela do banco e buscar os registros de acordo com a filial desejada e com os níveis de acesso do usuário que está executando. Se ele tem acesso e optar por ver todos os registros, ele deve ver todos os registros.

2. Depois de selecionado um intervalo, os registros serão carregados em 1 browse que tenha a opção de selecionar os itens.

3. Ao selecionar um ou mais registros, o usuário pode enviar a seleção para outro browse e continuar buscando outros registros de outras filiais (na parte superior da tela, há filtros para isso).

Nos dois browses, mencionados nos itens 2 e 3, estou usando arrays (por ser mais rápido). Eu consigo marcar/desmarcar e "mover" os registros de um browse para outro rapidamente.

PROBLEMA: a lentidão está no item 1, quando tenho que preencher o primeiro array (que será mostrado no item 2). Faço um DbSelectArea() na minha tabela e filtro com o SET FILTER TO. O problema está na lógica abaixo, que - conforme mencionei anteriormente - preenche o primeiro array:

meuAlias->(DbGotop())

While !meuAlias->(EOF())
aadd(aMeuArray ,{meuAlias->campo1,meuAlias->campo2, .F.})
meuAlias->(DbSkip())
Enddo

Preencher rapidamente um array com todos os dados do Alias

MensagemEnviado: 18 Jul 2018 08:30
por joaorenes
Já em array.... vai ter que ler o arquivo inteiro antes de apresentar alguma coisa.
Se for arquivo gigante...


Eu tentei outras opções, como criar um arquivo/tabela temporária, mas não tive progressos. Em algum momento, seja no preenchimento do browse ou durante a execução do método "marcartudo", a lentidão volta. Até criei um campo de marcação na tabela, mas essa abordagem não funcionou como esperado.

Enfim... Estou tentando :%

Preencher rapidamente um array com todos os dados do Alias

MensagemEnviado: 24 Jul 2018 00:05
por rochinha
Amiguinhos,

joaorenes
O seu exemplo me pareceu estar acessando uma tabela .DBF. Portanto a seguinte postagem tem os subsídios necessários para a sua filtragem.

Relatório Demorado

Preencher rapidamente um array com todos os dados do Alias

MensagemEnviado: 24 Jul 2018 11:50
por asimoes
PROBLEMA: a lentidão está no item 1, quando tenho que preencher o primeiro array (que será mostrado no item 2). Faço um DbSelectArea() na minha tabela e filtro com o SET FILTER TO. O problema está na lógica abaixo, que - conforme mencionei anteriormente - preenche o primeiro array:


SET FILTER vai deixar mais lento mesmo, eu trocaria por OrdScope ou indice temporário para filtrar.

Exemplo essa tabela tem um campo UTI que recebe S ou N

ADMSAUDE->(OrdSetFocus("admsau-0"))
ADMSAUDE->(OrdScope(0, 'S'))
ADMSAUDE->(OrdScope(1, 'S'))
ADMSAUDE->(DbGoTop())

Ou criar um indice temporário para filtrar

INDEX ON UTI TAG UTI FOR UTI = 'S' .AND. ! Deleted() TEMPORARY ADDITIVE

ADMSAUDE->(DbGoTop())