Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Conexión con bases de datos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Conexión con bases de datos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 26-05-2005
Avatar de sitrico
[sitrico] sitrico is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Caracas, Venezuela
Posts: 295
Poder: 22
sitrico Va por buen camino
Unhappy Un Insert muy lento.........

Estoy trabajando en los reportes de una aplicación y opté por usar un procedimiento para generar una tabla local temporal (BDE) para almacenar las lineas del reporte y luego generar la salida usando un TQuickRep.

Todo funciona razonablemente bien pero el rendimiento es patetico, haciendo diversas pruebas logre detectar que si quito la linea de "ExecSQL" que corresponde al insert de los datos en la tabla temporal el rendimiento cambia drasticamente (desgraciadamente no se genera el reporte ) pero agregar unos 400 registros en el archivo temporal toma hasta 20seg (si quito la linea "ExecSQL" todo el proceso dura menos de 1 seg) por lo que asumo que mi problema de rendimiento está directamente asociado al insert

Este es el código: (fDataMod.Q1 es un tQuery conectado a un TDatabase local).


Código Delphi [-]
With fDataMod.Q1 do
   Begin
   Sql.Clear;
   Sql.Add('Insert into '+CuotedStr(FName));
   Sql.Add('(CodMay, CodAux, Descrip, Ref, Concep, NumComp, FchComp,');
   Sql.Add(' M1, M2, M3, M4, LinTop, Bold, IdDetalle ) Values');
   Sql.Add('(:CodMay, :CodAux, escrip, :Ref, :Concep, :NumComp, :FchComp,');
   Sql.Add(' :M1, :M2, :M3, :M4, :LinTop, :Bold, :IdDetalle)');
   ParamByName('CodMay').AsString := Datos.CMay;
   ParamByName('CodAux').AsString := Datos.CAux;
   ParamByName('Descrip').AsString := Datos.Desc;
   ParamByName('Ref').AsString := Datos.Ref;
   ParamByName('Concep').AsString := Datos.Conc;
   ParamByName('NumComp').AsString := Datos.NComp;
   ParamByName('FchComp').AsDate := Datos.FComp;
   ParamByName('M1').AsCurrency := Datos.M1;
   ParamByName('M2').AsCurrency := Datos.M2;
   ParamByName('M3').AsCurrency := Datos.M3;
   ParamByName('M4').AsCurrency := Datos.M4;
   ParamByName('LinTop').AsInteger := Datos.LTop;
   ParamByName('Bold').AsBoolean := Datos.Bold;
   ParamByName('IdDetalle').AsInteger := Datos.IdDet;
   ExecSQL;
   End;
End;

¿ El uso de Parametros afecta (mucho) el rendimiento ?
¿ Que puedo hacer para acelerar el proceso de inserción ?

Gracias
__________________
Sitrico

Última edición por sitrico fecha: 26-05-2005 a las 23:34:23.
Responder Con Cita
  #2  
Antiguo 26-05-2005
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Curiosa manera de generar un reporte. ¿Por qué en lugar de crear una tabla temporal no simplemente haces una consulta SELECT de los datos que necesites y con ella alimentas al QuickReport?

// Saludos
Responder Con Cita
  #3  
Antiguo 27-05-2005
Avatar de sitrico
[sitrico] sitrico is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Caracas, Venezuela
Posts: 295
Poder: 22
sitrico Va por buen camino
Sabia que me iban a preguntar por eso,

La razón principal para generar el temporal es que entre otras características de la aplicación me pidieron que fuera capaz de generar los reporte tanto en impresoras de tinta y laser como en matriz de puntos (en formato plano) y la solución que encontré fue precisamente llenar un archivo temporal con los datos del reporte y luego llamar a un tQuickRep para la salida "Windows" y/o a un procedimiento para la la salida en Matriz de Puntos.

También debo aclarar que la mayoria de los reportes son bastante complejos (no son presisamente un simple listado de una o varias tablas) incluyen un monton de líneas adicionales que no están en la tabla, totales por nivel de grupo y otras cosas raras.

Por eso preferí pre-procesar el reporte y después generarlo, y también (aunque parezca mentira) porque me permite usar un código más consistente a la hora de administrar los QuickRep (Solo uso una clase base que heredo para la salida) creando los campos de reporte desde el código en tiempo de ejecución.

Pero, en el fondo tienes razón, normalmente es más fácil generar una consulta e imprimirla directamente.
__________________
Sitrico
Responder Con Cita
  #4  
Antiguo 27-05-2005
Mick Mick is offline
Miembro
 
Registrado: may 2003
Posts: 405
Poder: 22
Mick Va por buen camino
No indicas que tipo de tabla es, pero si es paradox o dbase, es infinitamente mas rapido usar un TTable y asignar los campos directamente.

Otra problema con esa query es que la estas limpiando y recreando continuamente (el Sql.Clear y Sql.Add) por cada registro, esto obliga al engine a parsear la sentencia cientos de veces, lo que aumenta tambien la lentitud, deberias asignar una sola vez la sentencia sql al principio, y despues simplemente solo asignar los parametros en el bucle.

La forma mas rapida es algo como esto:

Código:
// Tabla es un objeto TTable , creado previamente y con los campos
// añadidos en tiempo de diseño: Click boton derecho
// sobre el objeto TTAble -> Edit Fields -> Add Fields

Tabla.Append;
TablaCodMay.AsString := Datos.CMay;
TablaCodAux.AsString := Datos.CAux;
TablaDescrip.AsString := Datos.Desc;
TablaRef.AsString := Datos.Ref;
...
...
Tabla.Post;
Si no quieres usar variables persistentes para los campos, podrias hacer algo como lo siguiente (aunque la funcion FieldByName es mucho mas lenta que simplemente acceder directamente a los campos como en el ejemplo anterior):

Código:
Tabla.Append;
Tabla.FieldByName('CodMay').AsString := Datos.CMay;
Tabla.FieldByName('CodAux').AsString := Datos.CAux;
Tabla.FieldByName('Descrip').AsString := Datos.Desc;
Tabla.FieldByName('Ref').AsString := Datos.Ref;
...
...
Tabla.Post;
Ten en cuenta tambien los indices que haya definidos en la tabla temporal, cuantos mas indices tenga definidos mas lenta es la insercion de registros.

Saludos
Responder Con Cita
  #5  
Antiguo 27-05-2005
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 28
jachguate Va por buen camino
Para no cambiar mucho la estructura que ya tenes definida, podes valerte de tun TClientDataset o un TrxMemoryData, definir su estructura en tiempo de diseño y luego valerte de los métodos Insert/Post para rellenarlo. Esto no debiera añadir mas que algunos milisegundos a la operación de tu programa, pues todo se hará en memoria.

hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #6  
Antiguo 27-05-2005
Avatar de sitrico
[sitrico] sitrico is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Caracas, Venezuela
Posts: 295
Poder: 22
sitrico Va por buen camino
Gracias Roman, Mick y jachguate, voy a crear un tRXMemoryData (que es en en escencia un TTable) y lo manejo todo desde memoria. Ahora el asunto es donde crear el objeto, creo que lo voy a asociar directamente a mi reporte Base (el Dataset del reporte será un tRXMemoryData) y aplicaré las inclusiones directo a él.

Otra cosa ¿ Hay alguna diferencia entre tTable.Append y tTable.Insert ?. Yo siempre he usado el insert, pero la verdad no veo diferencias reales.

// Primeros resultados

Cita:
Otra problema con esa query es que la estas limpiando y recreando continuamente (el Sql.Clear y Sql.Add) por cada registro, esto obliga al engine a parsear la sentencia cientos de veces, lo que aumenta tambien la lentitud, deberias asignar una sola vez la sentencia sql al principio, y despues simplemente solo asignar los parametros en el bucle.
Probé mover el código que genera el SQL al principio del proceso para que sólo se "parseara" una vez y la diferencia de rendimiento fue mínima (mejoró menos de 1 seg).
__________________
Sitrico
Responder Con Cita
  #7  
Antiguo 27-05-2005
Avatar de sitrico
[sitrico] sitrico is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Caracas, Venezuela
Posts: 295
Poder: 22
sitrico Va por buen camino
Bueno, con el RxMemoryData el rendimiento es optimo (< 1 seg) para generar los temporales y al usar directamente la tabla del reporte también me permitio eliminar algo de código

El problema (generalmente hay uno) es que los reportes me los muestra en orden inverso y no encuentro la manera de indexar ó ordenar el RxMemoryData. ¿ Alguien sabe como ?

Gracias
__________________
Sitrico
Responder Con Cita
  #8  
Antiguo 27-05-2005
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por sitrico
¿ Alguien sabe como ?
Ni idea, pero si usases un ClientDataSet podrías ordenar por cualquier columna o columnas.

// Saludos
Responder Con Cita
  #9  
Antiguo 27-05-2005
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 28
jachguate Va por buen camino
No tiene propiedad IndexFieldNames?
__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #10  
Antiguo 30-05-2005
Avatar de sitrico
[sitrico] sitrico is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Caracas, Venezuela
Posts: 295
Poder: 22
sitrico Va por buen camino
Bueno, y sólo para futura referencia, el RxMemoryData no tiene (hasta donde sé) capacidad para ordenar o indexar archivos (mejor dicho estructuras de datos) la solución que encontre fue sustituir el "Insert" por un "Append".

Aparentemente y respondiendo mi pregunta anterior

Cita:
Empezado por Sitrico
¿ Hay alguna diferencia entre tTable.Append y tTable.Insert ?.
El "insert" incluye el registro antes del registro donde se encuentra el apuntador de la base de datos y por esto se generaba la aparente "inversión del orden de los registros" en la base de datos. Mientras que el "append" lo agrega al final del archivo y por lo tanto no causa el problema de la inversión.

En cuanto al rendimiento ahora mis reportes se generan en 1 seg.

Gracias a todos.
__________________
Sitrico
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 19:21:33.


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
Copyright 1996-2007 Club Delphi