Clipper On Line • Ver Tópico - Preencher rapidamente um array com todos os dados do Alias
Mudar para estilo Clássico
Discussão sobre outras linguagens de programação.
Postar uma resposta

Preencher rapidamente um array com todos os dados do Alias

17 Jul 2018 11:25

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

17 Jul 2018 15:06

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:
Código:
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

17 Jul 2018 15:51

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

17 Jul 2018 18:55

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

18 Jul 2018 08:23

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

18 Jul 2018 08:30

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

24 Jul 2018 00:05

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

24 Jul 2018 11:50

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())
Postar uma resposta