PDA

Ver la Versión Completa : Rutina muy lenta...


KAYO
03-07-2007, 17:04:24
Por alguna razon la rutina que os detallo va superlenta....., MDO con Firebird , Delphi 7 en XP.

estoy utilizando TMDOTable y tarda mas de 30 minutos en actualizar 900 registro con la siguiente rutina.

Agradezco vuestra paciencia en darme alguna pista de como optimizar esta rutina......


{Desactivo el MasterDetail}
Dm.TListasClientes.MasterSource := nil;
{filtro la tabla para que solo se contabilicen los registros NO ENTREGADOS}
Dm.TListasClientes.Filter := 'RECIBIDO = '+CHR(39)+'0'+CHR(39);
Dm.TListasClientes.Filtered := True;
DM.TListasClientes.Open;
DM.TListasClientes.Last;
{me voy al ultimo registro porque si no me aparece como si la base tuviese 0 registros para iniciar el progressbar}
ProgressBar1.Min := 0;
ProgressBar1.Max := DM.TListasClientes.RecordCount;
i := 0;
DM.TListasClientes.First;
while not DM.TListasClientes.eof do begin
i := i +1;
ProgressBar1.Position := i;
{verifico si existe en la base si existe para incrementar el aticulo y si no lo incluye}
if DM.TPedidosDetallados.Locate('NUMERO',DM.TListasClientesNumero.AsString,[loPartialKey]) then begin
DM.TPedidosDetallados.Edit;
DM.TPedidosDetalladosCantidad.AsInteger := DM.TPedidosDetalladosCantidad.AsInteger + (DM.TListasClientesCantidad.AsInteger-DM.TListasClientesCantidadRecibido.AsInteger);
DM.TPedidosDetalladosTotal.AsCurrency := DM.TPedidosDetalladosCantidad.AsInteger * DM.TPedidosDetalladosCosto.AsCurrency;
end
else begin
{busco en la base de articulos para completar datos como precios y costos}
DM.TArticulos.Locate('Numero',DM.TListasClientesNumero.AsString,[loPartialKey]);
DM.TPedidosDetallados.Insert;
DM.TPedidosDetalladosNumero.AsString := DM.TListasClientesNumero.AsString;
DM.TPedidosDetalladosCantidad.AsInteger := DM.TListasClientesCantidad.AsInteger-DM.TListasClientesCantidadRecibido.AsInteger;
DM.TPedidosDetalladosEditorial.AsInteger := DM.TArticulosEditorial.AsInteger;
DM.TPedidosDetalladosDepartamento.AsInteger := DM.TArticulosDepartamento.AsInteger;
DM.TPedidosDetalladosProveedor.AsString := DM.TArticulosProveedor.AsString;
DM.TPedidosDetalladosLinea.AsString := DM.TArticulosLinea.AsString;
DM.TPedidosDetalladosCurso.AsString := DM.TArticulosCurso.AsString;
DM.TPedidosDetalladosDescripcion.AsString := DM.TArticulosDescripcion.AsString;
DM.TPedidosDetalladosCosto.AsCurrency := DM.TArticulosCosto.AsCurrency;
DM.TPedidosDetalladosTotal.AsCurrency := DM.TPedidosDetalladosCantidad.AsInteger * DM.TPedidosDetalladosCosto.AsCurrency;
end;
DM.TListasClientes.Next;
end;
DM.TListasClientes.Close;
DM.TListasClientes.Filtered := False;
ProgressBar1.Position := 0;



ESPERO SE ENTIENDA!!!!

Neftali [Germán.Estévez]
03-07-2007, 17:40:32
Yo, a priori lo que haría sería poner unas mnarcas de tiempo para detectar qué es lo que está tardando más.
No comentas cuantos artículos tienen las otras tablas.
Revisa que tienes definidos los índices para las búsquedas y que se están utilizando.
El tema del First/Last seguidos no es recomendable porque obligas a cargar todos los registros (aunque con 900 no debería ser problema).
Si puedes evitar los loPartialKey en las búsquedas mejor.
Asegúrate del tiempo que están tardando los Locate.
Como alternativa al LOCATE lanza una SQL con TOP 1.
Si tienes controles visuales "linkados" inhabilitalos para ver si mejora.

NOTA: Sin tener más datos apuesto por que son los LOCATE. ;)

papulo
03-07-2007, 17:47:54
Yo, a priori lo que haría sería poner unas mnarcas de tiempo para detectar qué es lo que está tardando más.
No comentas cuantos artículos tienen las otras tablas.
Revisa que tienes definidos los índices para las búsquedas y que se están utilizando.
El tema del First/Last seguidos no es recomendable porque obligas a cargar todos los registros (aunque con 900 no debería ser problema).
Si puedes evitar los loPartialKey en las búsquedas mejor.
Asegúrate del tiempo que están tardando los Locate.
Como alternativa al LOCATE lanza una SQL con TOP 1.
Si tienes controles visuales "linkados" inhabilitalos para ver si mejora.

NOTA: Sin tener más datos apuesto por que son los LOCATE. ;)

Los LOCATE son mas ineficiente que ha podido parir madre. Por dios! Teníamos al principio de un programa una funcion con LOCATE sobre una tabla con 15 o 20 items y tardaba unos 60 segundos en arrancar. Encontré otro método para hacer las busquedas y eliminamos los LOCATE, ahora solo tarda 5 segs en arrancar ¡¡¡10 veces mas rápido!!!

Si son 900, tardará la de dios en encontrar lo que buscas.

Saludos.

roman
03-07-2007, 18:19:30
:eek:

una funcion con LOCATE sobre una tabla con 15 o 20 items y tardaba unos 60 segundos en arrancar

¡Hombre! No es que dude de tu palabra pero es que algo no andaba bien. Cierto que para búsquedas en tablas grandes será mejor una consulta SQL directa, pero con 20 registros, o aún con 1000, eso debe volar, incluso con PARADOX. O faltaban índices o te estabas trayendo uno a uno los registros desde el servidor, pero un minuto es demasiado.

:confused:

// Saludos

papulo
03-07-2007, 18:26:59
¡Hombre! No es que dude de tu palabra pero es que algo no andaba bien. Cierto que para búsquedas en tablas grandes será mejor una consulta SQL directa, pero con 20 registros, o aún con 1000, eso debe volar, incluso con PARADOX. O faltaban índices o te estabas trayendo uno a uno los registros desde el servidor, pero un minuto es demasiado.

Pensandolo mas pausadamente, creo que confundo dos recuerdos (debían estar en neuronas contiguas y en alguna borrachera se habrán ido a contarse sus historias, para acabar liandolas al final).

Por una parte, en una apliación, tenía que buscar entre unos miles de registros, unas referencias sin orden alguno y aunque disponía de indice, usaba la función locate e iba mas lento aquello que el caballo del malo, por lo que deseché esa opción y utilicé otra diferente (ahora no recuerdo cual era :( pero si que me quedó grabado a fuego LOCATE-> KK).

Lo del arranque lento tenía que ver con otro tema diferente :P

xander
03-07-2007, 20:39:46
Mejor haz un procedimiento almacenado que haga esas operaciones y solo mandalo a llamar desde tu programa.

Seguro que si lo haces asi si se tarda 50 milisegundos será mucho tiempo.

Ahora si no quieres hacerme caso con lo del procedimiento almacenado prueba poner esto antes de ejecutar tu código:

DM.TListasClientes.DisableControls;
DM.TArticulos.DisableControls;
DM.TPedidosDetallados.DisableControls;


y al final le pones:

DM.TListasClientes.EnableControls;
DM.TArticulos.EnableControls;
DM.TPedidosDetallados.EnableControls;

Casimiro Notevi
03-07-2007, 20:44:53
Aparte de la lentitud de locate y esas cosas en tablas, tan sólo quería indicar que la ProgressBar no se usa así, sino que debes llamar a 'StepIt' que avanza la progressbar, no tienes que llevar el control del paso a paso.

Neftali [Germán.Estévez]
04-07-2007, 10:48:47
Una cosa más en relación a lo que ha comentado Casimiro y el uso de los progressbar; Dado que calculas el Max del ProgressBar a partir del número de registros de la tabla puedes obtener un max de 900, 1000 o 5000.

Imagina un ProgressBar que tiene como mínimo 0 y como máximo 5000...
¿Tiene sentido? ¿Son apreciables para el usuarios los 5000 cambios en el Progress? ¿Es necesario repintar (costoso) el progress 5000 veces?:confused::confused::confused:
Yo creo que no.

En estos casos, lo que hago es no repintar el Progress más de 25 o 50 veces.
Puedes utilizar un MOD para que en lugar de pintar 900 pasos pinte 25 (en este caso un Step cada 36 registros); Es más eficiente y el efecto para el usuario la mayoría de veces es inapreciable.

NOTA: Cuanto mayor es el número de pasos más se aplica lo comentado.
NOTA2: Hay que tener en cuenta que el proceso no vaya a tardar 5 minutos y sólo mostremos 25 pasos... Nunca perder de vista el tiempo que puede tardar el proceso, para que la visualización sea correcta.

roman
04-07-2007, 16:45:13
Esto me llama la atención. Suena perfectamente razonable lo que dices del repintado, pero, a decir verdad, quizá un poco por flojera, yo siempre pongo el ProgressBar.Max al máximo (valga la redundancia) y el Step en 1 y no noto que haya ningún problema. Seguro que el usuario no aprecia 5000 cambios, pero, ¿realmente hay cinco mil cambios visuales? Porque yo tengo la impresión que el control dibuja una nueva porción sólo cuando realmente es necesario, o estaríamos viendo un parpadeo, y no lo aprecio.

// Saludos

KAYO
04-07-2007, 16:59:11
Agradezco vuestra atención. El problema estaba básicamente en el componente TMDOTable q se rayó (me costo un monton detectarlo), pero solucione el problema simplemente eliminando e incluyendo de nuevo el componente TMDOTable:confused: . Claro q tambien optimice las busquedas utilizando SQL's como me habeis recomendado en vez de los locate...

DE NUEVO MUCHAS GRACIAS A TODOS POR VUESTRA ATENCION!!!!

roman
04-07-2007, 17:14:44
Pero, exactamente, ¿cuál fue el problema? Porque daría entonces la impresión de que es mejor no usar esos componentes que pueden de pronto rayarse. :confused:

// Saludos