PDA

Ver la Versión Completa : ClientDataSet perdida de performance


juanmdq
07-05-2008, 14:26:51
Hola amigos del club.
Utilizando Delphi 7 y Oracle me ocurrió la siguiente interrogante cuando realizaba un proceso de importacion de archivo ascii a una tabla temporal plana, es decir, lo único que tiene la tabla es un campo 'renglon' de tipo varchar2 sin indices ni nada de nada.
Para el algoritmo utilizo un timer para actualizar un reloj y un thread que es el encargado de recorrer el ascii y cada cierta cantidad de renglones enviarlo a oracle.
El programa es +/- asi:

AbrirArchivo(txt);
dmDataModule.cdsArchivo.DisableControls;
dmDataModule.cdsArchivo.Open;
nrolinea := 0;
while (not eof(txt)) and (not terminar) do
begin
nrolinea := nrolinea + 1;
readln(txt, line);

dmDataModule.cdsArchivo.Insert;
dmDataModule.cdsArchivoRENGLON.AsString := line;
dmDataModule.cdsArchivo.Post;

if (nrolinea mod 1500) = 0 then
dmDataModule.cdsArchivo.ApplyUpdates(-1);
end;
dmDataModule.cdsArchivo.Close;


Cuando importo archivos chicos, por ej. de 4MB el programa funciona genial, lo realiza bastante rapido.
Ahora bien, cuando intento importar un archivo de 180 MB se arrastra cual tortuga caminando en barro. Lo extraño es que arranca joya pero cada vez le cuesta mas completar los porcentajes, por ejemplo, del 1% al 2% lo hace en 1 min. el 9% al 10% lo hace en 2min. y asi va perdiendo en performance de forma bastante alarmante.

¿ Alguien tiene idea de a que se puede deber esto ? :confused:

Desde ya muchas gracias !

coso
07-05-2008, 14:57:57
Creo que se debe precisamente a que no usas indices en la base de datos. Prueba de colocar un campo id como indice principal para que el servidor pueda ordenarlo todo segun mejor le convenga. Ya diras... (PD: si usas Append en vez de Insert, o AppendRecord, te ira ligeramente mas rapido, pues directamente se va al final y no recoloca el cursor)

tefots
07-05-2008, 15:16:16
usa append en vez de insert , como ya te han dicho , con insert ha de recolocar el cursor y con append no , por eso cada vez le cuesta mas.

Tambien aceleraria bastante que en vez de tener un tquery con un select , uses la sentencia sql directamente , insert into table (xxx,xxx,xx) values (xx,xx,xx) y hagas un query.execsql. mas que nada porque no es optimo tener un query de 180mb o mas en memoria (va creciendo conforme vas insertando)

y en vez de usar el applyupdates (que no tiene mucho sentido usando un execsql) , inicies y finalices la transaaccion cada x registros.

salud2.

juanmdq
07-05-2008, 16:20:49
Bueno, probe de cambiarle el insert por el append y mejoro algo aunque no lo suficiente.

Yo sigo intentando y cualquier cosa aviso.

Gracias por responder.

Al González
07-05-2008, 16:29:35
¡Hola a todos!

Te doy el mismo consejo que Tefots.

¿Por qué no ejecutar directamente las inserciones sobre la base de datos? ¿Realmente necesitas ese conjunto de datos en memoria con todos los registros transferidos?

Si por alguna razón necesitaras seguir usando un TClientDataSet, sin importar cual sea su contenido. Podrías intentar vaciándolo cada cierto número de registros transferidos.

Esperamos tus comentarios.

Saludos.

Al. :)

coso
07-05-2008, 18:27:53
Te doy unas cuantas ideas a ver si te van :

-quiza la velocidad se pierda debido a exceso de acceso a disco. Prueba de cargar todo el fichero de texto primero en memoria (no se si lo haces ahora mismo). Seguramente si lo cargas en un TMemo te lo explotará y lo deberas cargar dinamicamente tu a un String o a un puntero a string. (Memo1.LoadFromFile('fichero.txt'));

-Lo que te dije en el primer post. Lo has indexado? crea un campo id con indice, pues los servidores de BD a veces los usan internamente los indices para sus operaciones.

-Cambia todo a SQL y usa sentencias SQL.

Y si no necesitas la tabla, si solo es para cargar en ella el fichero de texto, entonces lo mejor es lo que te comente al principio : usa algun componente con strings directamente (TMemo, TStringList,etc...o un TStrings mismo, solo q tiene menos metodos y no se puede visualizar) y si los explota (180 MB son MB) entonces deberas programar a nivel de punteros.

Venga espero q te sirva.