Uso de letodb

Fórum sobre Banco de Dados e RDDs para Clipper/[x]Harbour.

Moderador: Moderadores

leandrolinauer
Usuário Nível 3
Usuário Nível 3
Mensagens: 413
Registrado em: 16 Out 2006 10:59
Localização: Paranaíba-MS

Uso de letodb

Mensagem por leandrolinauer »

Boa tarde Itamar.
"
Já disse pra ele o que fazer. Infelizmente ele não entendeu.
"
R: Parece que sim, não entendi, poderia ser mais claro porque nunca utilizei nada parecido.
"
Separar antes, pra não precisar ficar varrendo o DBF todo, mas ele disse que usar RELATION... AI eu não sei pq não uso isso desde muito tempo.
"
R: Coloquei neste módulo de pesquisa de produtos o RELATION mas não adiantou pra nada, DBSEEK estava fazendo a mesma coisa.
Motivo: Tenho uma tabela de produtos para cada loja em pastas diferentes, exemplo: nome do arquivo CEST0300.DBF
C:\DADOS\LOJA0001\BANCO\CEST0300.DBF ->LOJA 1 MATRIZ
C:\DADOS\LOJA0002\BANCO\CEST0300.DBF ->LOJA 2 FILIAL
C:\DADOS\LOJA0010\BANCO\CEST0300.DBF ->LOJA 10 FILIAL
O módulo é pra edição do cadastro dos produtos, então devo abrir todos eles em todas as pastas, certo, abro eles.
como não sei qual a pasta peço para o sistema rodar o CEMP0000 (cadastro das lojas) abrindo os arquivos e depois pesquisando os registros no caso com WHILE
Motivo: A pesquisa tanto pega um item, como 10 ou todos para mostrar na tela para editar de acordo com o usuário com o selecionamento.
Mas para pegar o mesmo registro em cada loja, ou faço um SEEK ou RELACIONO os registros.
SEEK leva o mesmo tempo do RELATION, então não adiantou eu relacionar as tabelas das filiais com a da MATRIZ.
Se eu faço uma pesquisa com um item ou outro com tomada pelos indices GRUPO, SUBGRUPO etc, aí sai rapidão, porque é claro, uso o índice, mas pra tabela toda, mesmo fazendo pelo grupo leva o tempão, pq vai pegar todos os dados.
Então dei uma olhada no SCOPE e vi que ele me resolveria mostrando o DBF da tabela ao invés do temporário, o que torna instantâneo.

Claro, se ainda não entendi é pq estou conhecendo estas opções agora, quanto a índices TEMPORARY ou MEMORY não entendi mesmo qual a diferença.
"
Tá relacionando 8 mil itens x 10 filiais. 80 mil itens... Não sei não vi o código.
Eu faço isso só que com INDEX FOR TEMPORARY e é quase instantâneo para 12 meses, em media 10 mil registros por mês.
"
R: Poderia me passar um exemplo um pouco mais detalhado?

Boa tarde José Quintas.
"
Se processa tudo, pesquisa tudo..... o relacionamento serve pra que ?
Sei lá....
"
R: Serve exatamente para pegar os registros em arquivos diferentes, devido a preço, estoque.

Fico muito grato a todos que puderem me elucidar melhor, a única coisa que sei é que precisava de relatórios e pesquisas tipo instantâneas, como fazê-las não tenho a idéia lucida sobre isto.

Vou pesquisar mais sobre indices temporarios.
Um abraço.
Harbour 3.2 + GtWVW + QT + SQLite3 + DBF + SQL (Firebird)
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Uso de letodb

Mensagem por Itamar M. Lins Jr. »

Olá!
É simples.
Como eu crio um indice com a clausula FOR ?
PoR exemplo ficha KARDEX da saida do produto com a palavra "CIMENTO" nome no meio de milhares de produtos.
INDEX ON produto TAG temp01 FOR "CIMENTO" $ produto TEMPORARY //Não tenho necessidade de criar milhares de indices 1 para cada produto por isso faço temporary pq irá ser jogado fora.
Depois disso faço um DO WHILE nesse indice só com esse produto. Pode ser EXATO só usar o código ou EAN etc.
DO WHILE .NOT. EOF()
Quando fechar o DBF, esse indice é descartado. Quer dizer dentro da ORDBAG(CDX) deixará de existir.
É só isso ai, mais nada.
No LetoDB:

Código: Selecionar todos

...
If re->(ordNumber("RE100")) > 0
   re->(ordDestroy("re100")) 
EndIf
...
cQuery := " dtos(vencimento) >= '"+DToS(dIni)+"' .and. dtos(vencimento) <= '"+DToS(dFim)+"' .and. empty(pagamento) "
OrdBy  := "cliente + dtos(vencimento) + cod_venda"
...
Index on &OrdBy Tag re100 for &cQuery temporary additive
...
Revelar as variáveis antes, pq o servidor LetoDB não sabe, não enxerga elas. Mesma coisa do SQL.
Basicamente é isso ai em cima. Faça com o produto que vc quer na matriz, abre as filiais e faz a mesma coisa.
LetoDb não sabe o que é dINI(data incial), dFim(Data final), não sabe de nenhuma variável.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Uso de letodb

Mensagem por Itamar M. Lins Jr. »

Olá!
Usando OrdScope()
No lugar de SET RELATION. (pra cortar/separar o que vc quer) dos demais registros.

Desejo separar todos os REGISTROS no arquivo de PRODUTOS VENDIDOS do mês de JANEIRO. cerca de 10 mil itens.
Primeira coisa é existir o INDICE com o CÓDIGO (Numero do Pedido) ou numero da NFe, ou outra coisa que vc use para saber de quem é.
Vamos supor que o REGISTRO(PONTEIRO) está em algum lugar do DBF PRINCIPAL ou USANDO um código(variável)
Estando o arquivo INDEXADO só basta isso ai em baixo. O arquivo que vai "receber" a ORDSCOPE()

(cArq)->(OrdScope(0, cab->pedido) ) //CAB é o ALIAS da MATRIZ ou do PEDIDO etc...
(cArq)->(OrdScope(1, cab->pedido) )

ou -> cCodigo := cab->pedido ou cab->nfe ou cab->ean

(cArq)->(OrdScope(0,cCodigo) )
(cArq)->(OrdScope(1,cCodigo) )

É só isso mesmo!
(cArq)->(OrdScope(0,cab->pedido) ) //O ZERO é o INICIO da CONDIÇÃO
(cArq)->(OrdScope(1,cab->pedido) ) //1 UM é o FIM da CONDIÇÃO

Aqui ele CORTOU o DBF retirou lá dos 10 mil apenas os itens do PEDIDO em questão.
EOF() e BOF() funciona!!!!
(cArq) -> (DbGoTop())
DO WHILE (cArq) -> ( ! eof() )

(cArq) -> (Dbskip())
ENDDO

Para DESLIGAR o ORDSCOPE!
(cArq)->(OrdScope(0,) )
(cArq)->(OrdScope(1,) )
Ou fechar o DBF que a ESCOPO(ORDEM) desliga.

TREINE ai com coisa SIMPLES! por favor! depois vc vai complicando!

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
ivanil
Usuário Nível 3
Usuário Nível 3
Mensagens: 166
Registrado em: 11 Set 2004 15:13
Localização: Florianópolis/SC

Uso de letodb

Mensagem por ivanil »

Mate uma curiosidade minha:
qual o conteúdo dessa função?
ShowWaitProc()
ivanil
Usuário Nível 3
Usuário Nível 3
Mensagens: 166
Registrado em: 11 Set 2004 15:13
Localização: Florianópolis/SC

Uso de letodb

Mensagem por ivanil »

é que essa função é chamada linha a linha do while... isso deve pesar legal, porque teoricamete há trafego alem de atualizar a tela 1 a 1... talvez uma chamada a cada 500...
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Uso de letodb

Mensagem por Itamar M. Lins Jr. »

Olá!
Apaguei, fiquei na duvida, deixa ele responder...
Mesmo assim não precisa.
Acho que faltou o ShowWaitProc(.T.) -> .T. //mesmo assim deve degradar, ligar, pois fica chamando.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Uso de letodb

Mensagem por JoséQuintas »

Você não está sendo muito claro nisso tudo.
Se entendi direito, está processando o equivalente a milhões de registros, ao invés de apenas 80.000

Só dá pra tentar adivinhar.....

Se no arquivo de fora filtra departamento, seção, códigos, etc.... é de se supor que está trabalhando com o arquivo de produtos da matriz.
Se no arquivo de dentro é cada filial, está processando 8.000 produtos pra cada produto da matriz.
8.000 x 8.000, 64 milhões.
pra 10 filiais, 640 milhões.

Sei lá.... tá confuso isso....

E esse IIF() maluco, confunde mais ainda.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
ivanil
Usuário Nível 3
Usuário Nível 3
Mensagens: 166
Registrado em: 11 Set 2004 15:13
Localização: Florianópolis/SC

Uso de letodb

Mensagem por ivanil »

Ele tem um cadastro de locais;
Ele faz um scan nesta tabela para varrer a estrutura e abrir os arquivos por locais distribuídos nos diretórios;
Nesses arquivos locais é que feito a varredura do que ele precisa com aquele monte de condições para criar a tabela temporária;

se só tem 8000 registros por tabela, a única coisa que me vem a mente é essas chamadas do ShowWaitProc...

Se fosse eu que estivesse com este problema, começaria por duplicando à rotina, desligaria todas as relações; tiraria os acompanhamentos e faria uma leitura bruta, porem limpa, 100% para medir o tempo, isso daria umas respostas que ele precisa. Pode ser tanta coisa e, ao mesmo tempo, pode ser uma bobagem qualquer que passa despercebido.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Uso de letodb

Mensagem por JoséQuintas »

Código: Selecionar todos

STATIC PROCEDURE New_BuscaProduto( oModo )

   LOCAL cFilter := ".T."

   DO CASE
   CASE Left( wMerc, 2 ) != "99" .AND. Substr( wMerc, 3, 2 ) != "99".And. Right( wMerc, 3 ) =="999"
      cFilter += [ .AND. Left( CODIGO, 4 ) == "] + LEFT( wMerc, 4 ) + ["]
   CASE Left( wMerc, 2 ) # 99 .AND. Right( wMerc, 5 ) === "99999"
      cFilter += [ .AND. Left( CODIGO, 2 ) == "] + LEFT( wMerc, 2 ) + ["]
   CASE wMerc != "99999999"
      cFilter += [ .AND. CODIGO == "] + CODIGO + ["]
   ENDCASE
   IF oGrupo != "9999"
      cFilter += [ .AND. GRUPO == "] + oGrupo + ["]
   ENDIF
   IF oSubGrupo != "9999"
      cFilter += [ .AND. SUBGRUPO == "] + oSubGrupo + ["]
   ENDIF
   IF oMarca != "9999"
      cFilter += [ .AND. MARCA == "] + oMarca + ["]
   ENDIF
   IF oModelo != "9999"
      cFilter += [ .AND. MODELO == "] + oModelo + ["]
   ENDIF
   IF oLinha != "9999"
      cFilter += [ .AND. LINHA == "] + oLinha + ["]
   ENDIF
   IF oClasse != "9999"
      cFilter += [ .AND. CLASSE == "] + oClasse + ["]
   ENDIF

   ShowWait(,,"Selecionando registros...")
   DbSelectArea("CEST0300") //seleciono o principal aberto da loja

   SET FILTER TO &(cFilter)
GOTO TOP

   DO WHILE CEST300->( ! Eof() ) .AND. ! wSaida

      wSaida := ExitSeek()

      ShowWaitProc()

      CEMP0000->(dbGoTop())
      DO WHILE CEMP0000->(!Eof())
         wSaida:=ExitSeek()
         ShowWaitProc()
         IF o_Acao == 6 .AND. CEMP0000->C_LOJA==wFilial
            lMatriz := .T.
         ELSEIF wGEco == "99999999" .OR. Left( CEMP0000->E_CGC, 8 ) == wGEco
            lMatriz := ( wLoja == "0001" .OR. wLoja == CEMP0000->C_LOJA )
         ELSE
            lMatriz := .F.
         ENDIF
         IF ! lMatriz
            SKIP
            LOOP
         ENDIF   
         hE_CGC := Left( CEMP0000->E_CGC, 8 )
         fP     := CEMP0000->C_LOJA
         v_Merc := CEST0300->CODIGO
         a_Area := "C300" + fP
         w_vTXT := fP + " - " + v_Merc + " - " + CEST0300->DESCRICAO
         DO CASE
         CASE o_Busca ;        lFilial := .T.
         CASE o_Acao == 1 ;    lFilial := .T.
         CASE o_Acao == 2 ;    lFilial := ( a_Area->P_VALOR > 0 )
         CASE o_Acao == 3 ;    lFilial := ( a_Area->DESCONTO > 0 )
         CASE b_Acao == 1 ;    lFilial := ( a_Area->Basico == "B" )
         CASE b_Acao == 2 ;    lFilial := ( a_Area->Basico != "B" )
         CASE b_Acao == 3 ;    lFilial := .T.
         CASE c_Acao == 1 ;    lFilial := ( a_Area->E_AT $ " S" )
         CASE c_Acao == 2 ;    lFilial := ( a_Area->E_AT == "N" )
         CASE c_Acao == 4 ;    lFilial := ChkInc()
         OTHERWISE             lFilial := .T.
         ENDCASE
         DO CASE
         CASE o_Acao == 6 .AND. v_Acao == 1; lFilial := ( a_Area->ATUAL > 0 )
         OTHERWISE   ;                       lFilial := .T.
         ENDCASE
         IF lFilial
            (File1Tmp)->( DbAppend() )
            (File1Tmp)->LOJA     := fP
            (File1Tmp)->UF       := CEMP0000->E_UF
            (File1Tmp)->E_CGC    := hE_CGC
            (File1Tmp)->CODIGO   := (a_Area)->CODIGO
            (File1Tmp)->TICADO   :=" "
            (File1Tmp)->E_AT     := (a_Area)->E_AT
            ......demais campos necessarios
         ENDIF
         CEMP0000->(dbSkip(1))
      ENDDO
      CEST300->( dbSkip(1) )
   ENDDO
   CloseWindow()

   RETURN Nil
Sei lá....
Tem também um ChkInc() aí no meio.
Tem mais arquivos envolvidos.
Difícl entender tanto filtro no primeiro, aparentemente com código de produto, e depois o outro aparentemente sem filtro relacionado.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
leandrolinauer
Usuário Nível 3
Usuário Nível 3
Mensagens: 413
Registrado em: 16 Out 2006 10:59
Localização: Paranaíba-MS

Uso de letodb

Mensagem por leandrolinauer »

Bom dia a todos.
"Itamar : INDEX ON produto TAG temp01 FOR "CIMENTO" $ produto TEMPORARY"
Uma dúvida, este índice seria criado ao acessar o cadastro do produto mas ele não ficaria demorado para criar ele, como na criação dos índices fixos da tabela?

"Ivanil : ShowWaitProc()"
É apenas uma função de processamento para mostrar na tela o andar do processamento, mostra de 100 em 100 registros, de 1 em 1 fica insuportável (rsrs).
Esta função fazer um carrinho de compras e um boneco andando para progressão, senão o usuário acha que travou.

Lá nas seleções só passa em algumas das funções se oAcao for correspondido, senão nem vê.
ChkInc() = checa os itens incompletos, faltando dados, tais como, peso, preço, ncm, cest, etc.

"José Quintas : While 8.000 registros"
Exemplo mais enxuto:
3 tabelas em 3 pastas diferentes de produtos.
1ª tabela é a da MATRIZ, a principal com todas as informações do produto e o estoque da MATRIZ.
as demais tabelas são das filiais no servidor principal, uma copia exata dos dados do produto mas o estoque, preço é dela própria.
Ao pesquisar, devo colocar na tela todos os dados de todas as lojas: exemplo tabela X
LOJA CÓDIGO DESCRICAO PREÇO ESTOQUE
0001 - 00001 - CIMENTO TAL - 10,00 20,00
0002 - 00001 - CIMENTO TAL - 11,50 15,00
......
0010 - 00001 - CIMENTO TAL - 9,50 30,00
Então para eu pegar as informações destas outras tabelas de acordo com o item selecionado na pesquisa, se for um ou todos, faço da seguinte forma:
While no principal da MATRIZ
pego o produto
While no banco das lojas
posiciono no item desejado acima nesta loja, através de um SEEK ou RELATION, da na mesma até em velocidade de processamento.
gravo os dados do produto já selecionado acima pegando os dados do principal e da loja selecionada como preços e estoque.

E assim vai na tabela toda MATRIZ ou somente nos itens desejados na pré-seleção feita antes.
Então, se tenho 8.000 itens e quero mostrar todos, pego os 8.000 itens x cada loja pra mostrar os valores como a tabela X acima.
se forem 10 lojas, daria 80.000 itens no temporário, a gente reclama da velocidade, mas imagina fazer isto no papel, leva anos.

Assim o usuário tem na tela os dados de todas as lojas.
Claro, daria pra fazer de n formas diferentes este acesso dos dados, fiz este modelo a anos atrás pelo menos uns 20 anos.
Até pesquisei na internet alguns modelos, mas tbem descobri outros menos eficazes do que este método meu aplicado.

Quanto ao SCOPE, creio que seria a melhor situação pra mim, eliminando os índices neste modulo.
Fiz teste em uma tabela de cidade e ficou muito show, será uma ótima opção, mas para eu usar na tabela de produtos, tenho que melhorar uns índices nela, farei.
Quanto a remover as seleções para fazer teste do while, leva um tempo tbem para percorrer a tabela toda, digo tabela toda quando uso pegar todos os itens.

Creio que respondi a todos, se houver mais dúvidas é só perguntar.
Vou fazer uns testes com a clausula TEMPORARY pra ver a performance.

Grato a todos, um abraço.
Harbour 3.2 + GtWVW + QT + SQLite3 + DBF + SQL (Firebird)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Uso de letodb

Mensagem por JoséQuintas »

Quer ver matriz e filiais no browse, é isso?
No estilo SQL seria um SELECT, então, fazer igual.

Código: Selecionar todos

aFiliais := { "fil1\arquivo", fil2\arquivo", "fil3\arquivo" }
USE MATRIZ
SET FILTER TO &( cFiltro )
oTBrowse := { ;
   { "MATRIZ", { || matriz->produto } } }
FOR EACH cFilial IN aFiliais
   cAlias := "FIL" + StrZero( cFilial:__EnumIndex(), 2 )
   USE ( cFilial ) ALIAS ( cAlias )
   FOR EACH xAlias IN cAlias
      AAdd( oTBrowse, ;
         { xAlias, { || ( xAlias )->( DBSeek( matriz->Produto ) ), ( xAlias )->NomeCampo } } )
   NEXT
NEXT
Browse( oTBrowse )
Ainda pode destacar as colunas com preço baixo, pra chamar atenção, ou sei lá o que.
E se gostarem da idéia, coloca monitor gigante pra ter mais colunas ao mesmo tempo.
zebrado no browse vai ser útil.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Uso de letodb

Mensagem por Itamar M. Lins Jr. »

Olá!
Uma dúvida, este índice seria criado ao acessar o cadastro do produto mas ele não ficaria demorado para criar ele, como na criação dos índices fixos da tabela?
É bem rápido.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Uso de letodb

Mensagem por Itamar M. Lins Jr. »

Olá!
Antigamente, eu não usava assim, trabalhava da forma que vc ainda trabalha. Fazendo DO WHILE no DBF todo.
Agora sempre, PRIMEIRO separo o que quero com INDICE TEMPORARY com a CLAUSULA FOR. Sempre e ORDSCOPE().
Te digo que em muitos casos é difícil perder para SGBD em velocidade. Tem que montar o servidor dedicado com 32Gib core i9, para fazer frente ao LetoDb. Se botar CPU dessas padrão core i5, 8Gib e não dedicado, como é o caso da maioria das lojas, o LetoDb é bem mais rápido, digo isso pq já comparei com Postgres e ele perdeu. Lógico que se colocar em maquinas melhores, é outra performance.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
leandrolinauer
Usuário Nível 3
Usuário Nível 3
Mensagens: 413
Registrado em: 16 Out 2006 10:59
Localização: Paranaíba-MS

Uso de letodb

Mensagem por leandrolinauer »

Valeu Itamar
Vou fazer testes desta forma, demoro um pouco pq não tenho muito tempo livre pra programar, mas em breve pretendo ter, me dedicar exclusivamente só para meus clientes com sistema.
Grato
Harbour 3.2 + GtWVW + QT + SQLite3 + DBF + SQL (Firebird)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Uso de letodb

Mensagem por JoséQuintas »

Só curiosidade:
Na sua assinatura indica usar SQLite3 e Firebird.
Como faz o uso deles?
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Responder