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 20-07-2006
PatrickM PatrickM is offline
Miembro
 
Registrado: jun 2006
Posts: 21
Poder: 0
PatrickM Va por buen camino
PacketRecords i FindKey (ClientDataSet - DBExpress)

Hola a todos,

Estoy con una aplicación que trabaja con tablas muy grandes 30 columnas por 20000 filas, algunas de ellas con campos blob.

Utilizo SQLDataSet -> TDataSetProvider -> TClientDataSet para conectarme a dichas tablas i necesito editar campos puntuales de la tabla (sin utilizar una consulta). En teoria se podria hacer directamente con el ClientDataSet pero me carga TODOS los registros cuando abro la tabla para editarla. Esto hace que reserve memoria para unas 300 MB.

A priori el tema se soluciona poniendo la propiedad PacketRecords con un valor mayor que zero para que solo se carguen algunos registros y no toda la tabla. Pero entonces me carga todos los campos cuando le hago el FindKey.

He probado de poner PacketRecords = 0 y entonces no me encuentra el registro con el FindKey.

Estoy desesperado ya no se que probar mas. El BDE no me daba estos problemas de memoria. Aunque se me ha pasado por la cabeza no voy a volver al BDE, pero me extraña que no haya una solucion a mi problema trabajando con los componentes de DBExpress.

A ver si alguien me puede hecha una mano,

un saludo.

Última edición por PatrickM fecha: 25-07-2006 a las 12:01:12.
Responder Con Cita
  #2  
Antiguo 20-07-2006
[pepon386] pepon386 is offline
Miembro Premium
 
Registrado: ene 2005
Ubicación: Valencia
Posts: 68
Poder: 20
pepon386 Va por buen camino
Vamos por partes:

Cita:
Empezado por PatrickM

Estoy con una aplicación que trabaja con tablas muy grandes 30 columnas por 20000 filas, algunas de ellas con campos blob.
Eso no son tablas muy grandes, mas bien normalitas .

Cita:
Empezado por PatrickM
Utilizo SQLDataSet -> TDataSetProvider -> TClientDataSet para conectarme a dichas tablas i necesito editar campos puntuales de la tabla (sin utilizar una consulta). En teoria se podria hacer directamente con el ClientDataSet pero me carga TODOS los registros cuando abro la tabla para editarla. Esto hace que reserve memoria para unas 300 MB.
Eso te pasa porque en la propiedad PacketRecord del ClientDataSet tienes el valor -1, que hace que te devuelva todos los registros, los cuales almacena en memoria.

Cita:
Empezado por PatrickM
A priori el tema se soluciona poniendo la propiedad PacketRecords con un valor mayor que zero para que solo se carguen algunos registros y no toda la tabla. Pero entonces me carga todos los campos cuando le hago el FindKey.
Esto es porque el FindKey recorre toda la tabla, y para ello se trae todos los paquetes de datos que necesita hasta tenerla toda en memoria. Nuevamente tienes todos los datos en el ClientDataSet.

Cita:
Empezado por PatrickM
He probado de poner PacketRecords = 0 y entonces no me encuentra el registro con el FindKey.
Porque poniendo ese valor te devuelve sólamente la estructura de las tablas.

Cita:
Empezado por PatrickM
Estoy desesperado ya no se que probar mas. El BDE no me daba estos problemas de memoria. Aunque se me ha pasado por la cabeza no voy a volver al BDE, pero me extraña que no haya una solucion a mi problema trabajando con los componentes de DBExpress.

A ver si alguien me hecha una mano, y asi a mi no me hechan a mi del trabajo.

un saludo.
Claro que la hay: Tienes que filtrar la información que te va a devolver la aplicación. Para ello tienes que acotar correctamente los datos que quieres obtener de la base de datos (clausula WHERE de la sentencia SQL).
Responder Con Cita
  #3  
Antiguo 20-07-2006
PatrickM PatrickM is offline
Miembro
 
Registrado: jun 2006
Posts: 21
Poder: 0
PatrickM Va por buen camino
Hola Pepon

Gracias por tus respuestas. Aunque sigo con el problema ya que no quiero usar una consulta, simplemente quiero usar el SQLDataSet/TSQLTable para MODIFICAR registros de la tabla, no para consultarlos. Tengo claro que con una consulta obtengo solo los resultados que yo quiero, hasta ahi llegamos. El problema que tengo es que el TClientDataSet me devuelve todos los registros, y yo solo quiero posicionarme, Edit, Post, y ApplyUpdates.

Sobre el tamaño de la tabla ... el numero de registros no es muy grande, pero el el tamaño de cada registro es de 24 KB, eso multiplicado por 20000 hacen 300 MB de buffer en memoria que se crea el CDS, a parte de que es un fichero historico y cada año va creciendo.

a ver si alguien me da una solution.

gracias.
Responder Con Cita
  #4  
Antiguo 21-07-2006
[pepon386] pepon386 is offline
Miembro Premium
 
Registrado: ene 2005
Ubicación: Valencia
Posts: 68
Poder: 20
pepon386 Va por buen camino
Como te he comentado antes, el problema reside en que haces que se cargen todos los registros de la base de datos. Lo correcto es que se traiga unas pocas decenas de registros. Antes de que el usuario pueda visualizar la información, deberías de solicitarle un rango de registros a mostrar: por id, fechas, un texto, etc... Todo depende de la información que almacenes en tu base de datos.
Responder Con Cita
  #5  
Antiguo 21-07-2006
PatrickM PatrickM is offline
Miembro
 
Registrado: jun 2006
Posts: 21
Poder: 0
PatrickM Va por buen camino
Hola Pepon,

Para visualizar los resultados uso una consulta, ya que al ser un fichero historico, solo intento muestro los resultados en un rango entrado por el usuario.

El problema es al intentar modificar la tabla con un TClientDataSet -> TDataSetProvider -> TSQLTable, ya que aunque pongas el PacketRecord>0, el FindKey se los patea todos, y se los carga en el buffer de memoria del CDS.

Estoy modificando la implementación del FINDKEY para que esto no pase. Cuando lo tenga lo cuelgo para quien le pueda interesar.

un saludo,
Responder Con Cita
  #6  
Antiguo 21-07-2006
[pepon386] pepon386 is offline
Miembro Premium
 
Registrado: ene 2005
Ubicación: Valencia
Posts: 68
Poder: 20
pepon386 Va por buen camino
¿Por qué no en vez de modificar la implementación del FindKey haces que el ClientDataSet tenga SOLO ese registro? Para hacer la búsqueda con el FindKey, previamente tienes que saber qué es lo que buscas. Pues en vez de hacer un FindKey, modificas la sentencia SQL para que te devuelva el/los registros que estás buscando. ¿Por qué no explicas un poco como es la tabla y como realizas la búsqueda?
Responder Con Cita
  #7  
Antiguo 21-07-2006
PatrickM PatrickM is offline
Miembro
 
Registrado: jun 2006
Posts: 21
Poder: 0
PatrickM Va por buen camino
Te explico, el problema es que la aplicación usaba BDE i se ha migrado todo a DBExpress. Digamos que seria imposible cambiar ahora todos los TTables por Consultas i UPDATES.

Ya he resuelto el problema modificando el FindKey del ClientDataSet. De todas formas gracias por el interes.

Aqui pongo el código para quien le pueda interesar:

Código Delphi [-]
 
// TClientDataSet.FindKey -> Recupera del Provider solo el registro buscado en FindKey
// 21/7/2006 - SPI - Patrick Mira Pedrol 
Function TTableSCS.FindKey(const KeyValues: array of const): Boolean;
var i: Integer;
    CampsClau: TStringList;
    ParamsFind: TParams;
    Packet: OleVariant;
    RecsOut: Integer;
Begin
  CampsClau:=TStringList.Create;
  ParamsFind:=TParams.Create;
  Try
    If PacketRecords>0 Then Begin
      // Obtenir camps clau
      CampsClau.Delimiter:=';';
      CampsClau.DelimitedText:=IndexFieldNames;
      // Crear parametres
      For i:=Low(KeyValues) To High(KeyValues) Do Begin
        Case KeyValues[i].vType of
          vtInteger:    Begin
                          ParamsFind.CreateParam(ftInteger, CampsClau.Strings[i], ptInput);
                          ParamsFind.ParamValues[CampsClau.Strings[i]]:=IntToStr(KeyValues[i].vInteger);
                        End;
          vtString:     Begin
                          ParamsFind.CreateParam(ftString, CampsClau.Strings[i], ptInput);
                          ParamsFind.ParamValues[CampsClau.Strings[i]]:=KeyValues[i].vString^;
                        End;
          vtAnsiString: Begin
                          ParamsFind.CreateParam(ftString, CampsClau.Strings[i], ptInput);
                          ParamsFind.ParamValues[CampsClau.Strings[i]]:=string(KeyValues[i].vAnsiString);
                        End;
        End;
      End;
      // Obtenir Record
      Packet:=Self.DoGetRecords(1, RecsOut, 0, '', PackageParams(ParamsFind));
      Self.AddDataPacket(Packet, False);
    End;
    // FindKey
    Result:=inherited FindKey(KeyValues);
  Finally
    ParamsFind.Free;
    CampsClau.Free;
  End;
End;

El TTableSCS es un tipo que me he creado para modificar el FindKey y otras cosas del ClientDataSet. Su declaración seria algo asi:

Código Delphi [-]
 
type

  TTableSCS = class(TClientDataSet)
    ...
  private
    ...
  public
    Function FindKey(const KeyValues: array of const); override;
    ...
  end;



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

Temas Similares
Tema Autor Foro Respuestas Último mensaje
dbExpress ClientDataSet.Refresh problema Neia Conexión con bases de datos 0 18-04-2005 20:14:11
RecordCount vs PacketRecords cesar_picazo Conexión con bases de datos 1 02-04-2005 21:26:57
Problemas con DBExpress - ClientDataset argami Conexión con bases de datos 4 26-07-2004 11:21:12
Problema con ClientDataSet y DBexpress JOMABRI Conexión con bases de datos 6 26-05-2004 18:32:53
DbExpress - Transacciones - más de un clientDataSet carlosmari Conexión con bases de datos 7 29-09-2003 20:07:54


La franja horaria es GMT +2. Ahora son las 04:46:05.


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