Problemas indice

Post Reply
diegopolverelli
Posts: 149
Joined: Thu Jun 21, 2007 3:26 pm

Problemas indice

Post by diegopolverelli »

Hola. Tengo una aplicacion que usa un indice que se compone de 3 _ de 5, 16 y 10 de largo cada uno. Antes utilizaba un
locate e igualaba cada campo de la base con una variable; ahora hago un indice, y busco las 3 variables concatenadas.

El problema es que a veces, con el indice, se producen errores; no me encuentra un registro que existe, y me genera un duplicado (si no encuentra, lo da de alta). Probe muchisimas variantes de carga (muchos items, un solo item, etc.) pero en principio funciona bien con el locate y con el indice, pero cuando pongo el programa en produccion, la version con indice, una de 15 falla, y el del locate no.

Obviamente tengo funcionando el del locate, pero como se imaginaran, la performance del mismo, especialmente cuando trabajo en red, es peor.

¿se les ocurre que puede estar pasando? el indice esta armado de manera correcta; la prueba está en que funciona bien en muchas oportunidades. En fin, espero me puedan orientar. Ya no se por donde buscar. Gracias. Atte.
User avatar
karinha
Posts: 4882
Joined: Tue Dec 20, 2005 7:36 pm
Location: São Paulo - Brasil

Post by karinha »

Muestra algo en la pratica, porfa.

Saludos.
João Santos - São Paulo - Brasil
diegopolverelli
Posts: 149
Joined: Thu Jun 21, 2007 3:26 pm

ejemplo

Post by diegopolverelli »

tengo una tabla st_stock indexada por
deposito+st_codigoart+st_lote (en in indice permamente)

hago un movimiento, tengo 10 productos que salen de stock:

hago un while, y segun el producto, lote y deposito de donde salen,
busco en la tabla st_stock y resto o sumo en un campo CANTIDAD. Si no esta el registro, agrego en st_stock un registro nuevo.
Si esa busqueda la hago asi:
loca for st_stock->coddep=xcoddep .and. st_stock->art_codig=xart_codig .and. st_stock->lote=xlote, y pongo el programa en produccion, funciona todo de 10... ahora, si uso el indice del cual hablo en los primeros renglones, tambien funciona bien, pero no siempre... a veces no me encuentra un registro que existe, y por ende, al agregar, me duplica un registro.

Es rarisimo. Trabajo en red contra un server, con fwh 803... en fin Gracias...!!!
User avatar
karinha
Posts: 4882
Joined: Tue Dec 20, 2005 7:36 pm
Location: São Paulo - Brasil

Post by karinha »

Porque usas LOCATE en vez de DBSEEK()??

al agregar, me duplica un registro.

Esto és en una ALTERACION? Trabas el registro antes con RLOCK()?


Saludos.
João Santos - São Paulo - Brasil
diegopolverelli
Posts: 149
Joined: Thu Jun 21, 2007 3:26 pm

Post by diegopolverelli »

yo hago

seek xcoddep+xartcodig+xlote
if !eof()

modifico el reg

else

agrego el registro

endif


de esa menera funciona, pero a veces el seek falla, entra por el else, a pesar de existir la combinacion coddep+artcodig+lote, y me da de alta algo que ya existe.

si en lugar del seek uso locate (abro la base sin indexar incluso), no falla nunca. Rarisimo...
User avatar
Armando Picon
Posts: 448
Joined: Mon Dec 26, 2005 9:11 pm
Location: Lima, Peru

Post by Armando Picon »

LOCATE trabaja bien porque ubica la cadena que buscas sin importar el tamaño del campo... Cuando utilizas el índice, el mecanismo de búsqueda es ubicar el valor de tu cadena "con el mismo largo".

Mi sugerencia es que hagas una sentencia como esta, para crear tu índice:

INDEX ON PADL(Libros->Epoca,LEN(Libros->Epoca))+ ;
PADL(Libros->Orden,LEN(Libros->Orden))+ ;
PADL(Libros->numlibro,LEN(Libros->numlibro)) ;
TAG "LIBRO1" TO "LIBROS.CDX"

Como puedes ver en este índice se puede buscar el valor de tu variable + los espacios necesarios para completar el ancho del campo correspondiente...
FWH + BCC582 + WorkShop 4.5 + Resource Hacker + Mingw
Mis nuevas herramientas
Comunicacion via WhatsApp (+51) 957549 665
Comunicación via Correo: apic1002002 at yahoo dot es; apic1002002@gmail.com
diegopolverelli
Posts: 149
Joined: Thu Jun 21, 2007 3:26 pm

Post by diegopolverelli »

yo no uso .cdx

igualmente tengo indices sin usar esto del Len y demas, y funcionan bien; Antes del Seek pongo set softseek off y creo que funciona bien. ¿no tienen conocimiento de algun error aleatorio que se verifique con los indices?

ademas, el locate, si hago:

loca for st->cod=xcod1 .and. st->lote=xlote1

y tengo en st->lote, por ej, a001 y a0012, puede darse que me actualice mal: si xlote1=a001, quisas el locate me de .t. en a0012

¿o no? en fin. Gracias. Atte.
Ruben D. Fernandez
Posts: 189
Joined: Sun Jul 08, 2007 1:46 am
Location: Uruguay

Post by Ruben D. Fernandez »

Diego:
Prueba a poner antes del segundo dBseek(lo_que_buscas) un dbgotop().

Saludos

Ruben Fernandez.
User avatar
karinha
Posts: 4882
Joined: Tue Dec 20, 2005 7:36 pm
Location: São Paulo - Brasil

Post by karinha »

xlote1=a001, quisas el locate me de .t. en a0012


mira se no hay una cadena en blanco e retira los blancos con ALLTRIM().

OTRA:

locate for st->cod==xcod1 .and. st->lote==xlote1 //-> Intente asi.

Saludos.
João Santos - São Paulo - Brasil
User avatar
Armando Picon
Posts: 448
Joined: Mon Dec 26, 2005 9:11 pm
Location: Lima, Peru

Post by Armando Picon »

No necesitas usar el CDX, lo puse solo como ejemplo. Locate te va ha ubicar a001 correctamente si fue introducido primero antes que a0012... en caso contrario SIEMPRE se va ha colocar sobre a0012 porque ya contiene la cadena "a001". En Clipper ese fenómeno no ocurría. Por eso es que empece a utilizar PADL(alias->campo1, LEN(alias->campo1)) con la ventaja adicional que, sin importar las variaciones de la longitud del campo, puedo reindexar... y hasta el presente me funciona al 100%
diegopolverelli wrote:yo no uso .cdx

igualmente tengo indices sin usar esto del Len y demas, y funcionan bien; Antes del Seek pongo set softseek off y creo que funciona bien. ¿no tienen conocimiento de algun error aleatorio que se verifique con los indices?

ademas, el locate, si hago:

loca for st->cod=xcod1 .and. st->lote=xlote1

y tengo en st->lote, por ej, a001 y a0012, puede darse que me actualice mal: si xlote1=a001, quisas el locate me de .t. en a0012

¿o no? en fin. Gracias. Atte.
FWH + BCC582 + WorkShop 4.5 + Resource Hacker + Mingw
Mis nuevas herramientas
Comunicacion via WhatsApp (+51) 957549 665
Comunicación via Correo: apic1002002 at yahoo dot es; apic1002002@gmail.com
Carlos Mora
Posts: 988
Joined: Thu Nov 24, 2005 3:01 pm
Location: Madrid, España

Post by Carlos Mora »

Armando,

hacer un PADL(alias->campo1, LEN(alias->campo1)) no tiene sentido en el índice. Hay que hacerlo en la clave, al hacer el seek:

Seek PADL( cVar1, LEN(alias->campo1))+PADL( cVar2, LEN(alias->campo2))+PADL( cVar3, LEN(alias->campo3))

Ahí si tiene sentido. SIEMPRE campo1 tiene una longitud Len(campo1), es una identidad, no cambia nada.

Un saludo,

Carlos.
Saludos
Carlos Mora
http://harbouradvisor.blogspot.com/
StackOverflow http://stackoverflow.com/users/549761/carlos-mora
“If you think education is expensive, try ignorance"
User avatar
Armando Picon
Posts: 448
Joined: Mon Dec 26, 2005 9:11 pm
Location: Lima, Peru

Post by Armando Picon »

Carlos

Si tiene y muchísimo... mi preferencia es construir el indice con el PAD ya que en adelante no tengo que preocuparme de estar revisando en que parte del codigo, que podrían ser muchísima líneas, debo estar revisando para que no se vaya algo que luego no me devuelva el dato que busco con el Seek o Dbseek... (claro que utilizo rutinas que crean los índices al inicio y mantengo abierto las bases). Por otra parte mis variables de búsqueda las construyo, por ejemplo, vCampo1 := SPACE(LEN(Campo1)) y así sucesivamente de forma tal, que aunque por razones insospechadas tenga que modificar la losngitud del campo, no tengo que realizar ajuste alguno a mi código.

No hace mucho, enfrenté un problema con código parecido a lo que indicas en tu respuesta (realizar un adecuación de codigo contable para pasar de 6 dígitos de cuenta a 8 dígitos) y la verdad que fue horroroso el trabajo... tuve que trabajar a pérdida por que la revisión y modificación de código de terceros es peor que tortura china...!!!

Carlos Mora wrote:Armando,

hacer un PADL(alias->campo1, LEN(alias->campo1)) no tiene sentido en el índice. Hay que hacerlo en la clave, al hacer el seek:

Seek PADL( cVar1, LEN(alias->campo1))+PADL( cVar2, LEN(alias->campo2))+PADL( cVar3, LEN(alias->campo3))

Ahí si tiene sentido. SIEMPRE campo1 tiene una longitud Len(campo1), es una identidad, no cambia nada.

Un saludo,

Carlos.
FWH + BCC582 + WorkShop 4.5 + Resource Hacker + Mingw
Mis nuevas herramientas
Comunicacion via WhatsApp (+51) 957549 665
Comunicación via Correo: apic1002002 at yahoo dot es; apic1002002@gmail.com
User avatar
FranciscoA
Posts: 1964
Joined: Fri Jul 18, 2008 1:24 am
Location: Chinandega, Nicaragua, C.A.

Post by FranciscoA »

diegopolverelli wrote:yo hago

seek xcoddep+xartcodig+xlote
if !eof()

modifico el reg

else

agrego el registro

endif


de esa menera funciona, pero a veces el seek falla, entra por el else, a pesar de existir la combinacion coddep+artcodig+lote, y me da de alta algo que ya existe.

si en lugar del seek uso locate (abro la base sin indexar incluso), no falla nunca. Rarisimo...

Prueba de esta manera:

seek xcoddep+xartcodig+xlote
if Found() // en vez de !eof()
modifico el reg
else
agrego el registro
endif


O, asi:

if dbseek( xcoddep+xartcodig+xlote )
modifico el reg
else
agrego el registro
endif
Carlos Mora
Posts: 988
Joined: Thu Nov 24, 2005 3:01 pm
Location: Madrid, España

Post by Carlos Mora »

Hola Armando,
Armando Picon wrote: Si tiene y muchísimo...
realmente no me imagino donde podria tener algo que ver, por más que le doy vueltas, no se me ocurre como puede llegar a fallar.

¿Podrías enviarme una dbf con un ejemplo donde:

Code: Select all

PADL(alias->campo1, LEN(alias->campo1)) <> alias->campo1 
?
En lo que me dices del codigo contable cambiado de 6 a 8, si has cambiado un campo y no has reindexado evidentemente te saldrá mal. Y de hecho Harbour, a diferencia del Clipper, no acepta claves de longitud variable, por lo que usar el indice con las claves a 6 probablemente te hubiese resultado en un 'Corruption detected'. Por ejmplo usar claves variables como alltrim(nombre) falla en harbour en cuanto una clave no tien el mismo largo que la del registro 1.

Respecto de lo valores en blanco, siempre uso el registro fantasma del Eof() como base para los registros en blanco, es algo muy seguro. De hecho hace poco Manu Expósito puso una clase buffer, que es muy parecida a la que uso, y no he tenido nunca problemas.

Un saludo,

Carlos.
Saludos
Carlos Mora
http://harbouradvisor.blogspot.com/
StackOverflow http://stackoverflow.com/users/549761/carlos-mora
“If you think education is expensive, try ignorance"
Post Reply