Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   ClientDataSet perdida de performance (https://www.clubdelphi.com/foros/showthread.php?t=56088)

juanmdq 07-05-2008 14:26:51

ClientDataSet perdida de performance
 
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:
Código:

      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.


La franja horaria es GMT +2. Ahora son las 12:18:44.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi