Ir al contenido


Foto

[RESUELTO] como actualizo la base de datos sin usar refresh


  • Por favor identifícate para responder
26 respuestas en este tema

#1 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 31 diciembre 2009 - 08:31

Lo que hago es esto


delphi
  1. if Trim(Evento) <> '@' then
  2.   begin
  3.     DMmonitoreo.ZQuery1.Close;
  4.     DMmonitoreo.ZQuery1.sql.Clear;
  5.     DMmonitoreo.ZQuery1.SQL.Add('insert into central (csid,buffer,formato,evento,detalle,fechan )');
  6.     DMmonitoreo.ZQuery1.SQL.add('  values (:pcsid,:pbuffer,:pformato,:pevento,:Pdetalle,:pfechan)');
  7.     DMmonitoreo.zquery1.parambyname('pcsid').asstring :=trim(csid);
  8.     DMmonitoreo.zquery1.parambyname('Pbuffer').asstring :=buffer;
  9.     DMmonitoreo.zquery1.parambyname('pformato').asstring :=formato;
  10.     DMmonitoreo.zquery1.parambyname('Pevento').asstring :=trim(evento);
  11.     DMmonitoreo.zquery1.parambyname('Pdetalle').asstring :=detalle;
  12.     DMmonitoreo.zquery1.parambyname('pfechan').asdatetime :=now;
  13.     DMmonitoreo.ZQuery1.ExecSQL;
  14.     DMmonitoreo.ZQuery1.close;
  15.     DMmonitoreo.ZQuery1.SQL.text:='select first 10 * from central left join evento on central.evento=evento.evento order by entradadatos desc';
  16.     DMmonitoreo.ZQuery1.Open;
  17.  
  18.     if Dmmonitoreo.ZQuery1TIPO.AsString = 'A' THEN
  19.     begin
  20.     DMmonitoreo.ZQuery2.Close;
  21.     DMmonitoreo.ZQuery2.sql.Clear;
  22.     DMmonitoreo.ZQuery2.SQL.Add('insert into activas (csid,evento,fechan,entradadatos)');
  23.     DMmonitoreo.ZQuery2.SQL.add('  values (:pacsid,:paevento,:Pafechan,:paentradadatos)');
  24.     DMmonitoreo.zquery2.parambyname('pacsid').asstring := DMmonitoreo.ZQuery1CSID.AsString;
  25.     DMmonitoreo.zquery2.parambyname('Paevento').asstring :=dmmonitoreo.ZQuery1EVENTO.AsString;
  26.     DMmonitoreo.zquery2.parambyname('pafechan').asdatetime := DMmonitoreo.ZQuery1FECHAN.AsDateTime;
  27.     DMmonitoreo.zquery2.parambyname('Paentradadatos').asinteger := DMmonitoreo.ZQuery1ENTRADADATOS.asinteger;
  28.     DMmonitoreo.ZQuery2.ExecSQL;
  29.     DMmonitoreo.ZQuery2.close;
  30.     DMmonitoreo.ZQuery2.SQL.text:='select first 10 * from activas left join evento on activas.evento=evento.evento order by alarmnum desc';
  31.     DMmonitoreo.ZQuery2.Open;
  32.  
  33.  
  34.  
  35.   End;
  36.  
  37. end;   




y en el datamodule esto:



delphi
  1. procedure TDMmonitoreo.ZQuery1AfterInsert(DataSet: TDataSet);
  2. begin
  3. DMmonitoreo.ZQuery1.Active:=true;
  4. DMmonitoreo.ZQuery1.Refresh;
  5. DMmonitoreo.zquery1.Last;
  6. end; 




cuando eran pocos registros no habia problemas, pero ahora que son muchos el proceso se hace muy lento.


Lo que necesito es que cuando llega un nuevo registro la base de datos se actualice sin que sea tan lento.

PD. Me encantaria hacerlo con un SP, pero no se como utilizarlos, rolphy dame una mano con eso.

saludos

y gracias



  • 0

#2 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 31 diciembre 2009 - 09:03

¿Intentaste cerrar y abrir la tabla en vez de usar Refresh?



delphi
  1. procedure TDMmonitoreo.ZQuery1AfterInsert(DataSet: TDataSet);
  2. begin
  3. DMmonitoreo.ZQuery1.Close;
  4. DMmonitoreo.ZQuery1.Open;
  5. DMmonitoreo.zquery1.Last;
  6. end;



Saludos.
  • 0

#3 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 31 diciembre 2009 - 09:05

Gracias Enecumene por tu respuesta, voy a interntarlo pero me parece que el problema esta en el last
  • 0

#4 razadi

razadi

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 681 mensajes
  • LocationMéxico D.F.

Escrito 31 diciembre 2009 - 09:06

Que tal amigo Luk2009, mira yo resolví este problema haciéndome el procedure siguiente:


delphi
  1. procedure QueryRefresh(qQuery: TQuery);
  2. begin
  3.   qQuery.Close;
  4.   qQuery.Open;
  5. end;


ya tu le puedes agregar el Last, si te quieres ir al último o dejarlo así para que se vaya al primero.

y lo llamarias de la siguiente manera:


delphi
  1.   ...
  2.   QueryRefresh(DMmonitoreo.ZQuery1);
  3.   DMmonitoreo.zquery1.Last;
  4.   ...



Espero te sirva, es un poco ortodoxo pero a mi me resolvió la vida, saludos.
  • 0

#5 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 31 diciembre 2009 - 09:08

Gracias Enecumene por tu respuesta, voy a interntarlo pero me parece que el problema esta en el last


No creo amigo, el refresh no funciona correctamente cuando se trata de mucho registros.
  • 0

#6 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 31 diciembre 2009 - 10:12

Gracia razadi por tu respuesta. 

Veo que lo que me dices es que cree ese procedure y lo ponga debajo de estas lineas:

begin
    DMmonitoreo.ZQuery1.Close;
    DMmonitoreo.ZQuery1.sql.Clear;
    DMmonitoreo.ZQuery1.SQL.Add('insert into central (csid,buffer,formato,evento,detalle,fechan )');
    DMmonitoreo.ZQuery1.SQL.add('  values (:pcsid,:pbuffer,:pformato,:pevento,:Pdetalle,:pfechan)');
    DMmonitoreo.zquery1.parambyname('pcsid').asstring :=trim(csid);
    DMmonitoreo.zquery1.parambyname('Pbuffer').asstring :=buffer;
    DMmonitoreo.zquery1.parambyname('pformato').asstring :=formato;
    DMmonitoreo.zquery1.parambyname('Pevento').asstring :=trim(evento);
    DMmonitoreo.zquery1.parambyname('Pdetalle').asstring :=detalle;
    DMmonitoreo.zquery1.parambyname('pfechan').asdatetime :=now;
    DMmonitoreo.ZQuery1.ExecSQL;
    DMmonitoreo.ZQuery1.close;
    DMmonitoreo.ZQuery1.SQL.text:='select first 10 * from central left join evento on central.evento=evento.evento order by entradadatos desc';
    DMmonitoreo.ZQuery1.Open;
   


y no tendria que usar el afterInsert del datamodule.


Amigo Enecumene, ya estoy cerrando y abriendo el query cuando grabo, solo me faltaria incluir el last. donde deberia ponerlo.

PD. donde debo hacer un commit para que se registre de inmediato lo que grabado.
  • 0

#7 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 31 diciembre 2009 - 10:36

Pues precisamente debajo del open como te comenté en el post #1:



delphi
  1. procedure TDMmonitoreo.ZQuery1AfterInsert(DataSet: TDataSet);
  2. begin
  3. DMmonitoreo.ZConnection1.Commit;
  4. DMmonitoreo.ZQuery1.Close;
  5. DMmonitoreo.ZQuery1.Open;
  6. DMmonitoreo.zquery1.Last;
  7. end;



Prueba de esa forma.

Saludos.
  • 0

#8 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4.266 mensajes
  • LocationCosta Rica

Escrito 31 diciembre 2009 - 10:36

Hola
No entiendo??
Por que el Last??.
Si se inserta con solo tener un campo autonumerico bastaría, incluso sin el al hacer un insert se habre un nuevo registro al final.
Saludos.

  • 0

#9 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 31 diciembre 2009 - 11:02

Eso voy a probar ahora Caral, realmente si no lo pongo, el programa que revisa lo que va llegando a la base de datos no funciona. Ahora que le puse el commit dejame ver si el last no hace falta.

Gracias enecumente, voy a seguir probando te digo
  • 0

#10 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 31 diciembre 2009 - 11:31

Hola.

Pues a mi me parece que tu problema no está en el lado de Delphi, ya que tus consultas solo devuelven 10 registros (tienes un first 10 en ambas consultas). Por lo que con tan pocos registros, no deberías apreciar ninguna diferencia entre un Refresh o un Close y un Open.

Tiene todo el aspecto de que el problema está en la base de datos, en que el motor de base de datos tarda mucho tiempo en procesar ambas consultas.

Esto se soluciona facilmente, creando un índice en la tabla para que el optimizador de consultas de la base de datos pueda utilizar ese índice para localizar inmediatamente los registros que estás buscando.

En este caso concreto, tienes que añadir un índice para la tabla CENTRAL sobre el campo entradadatos en descending. Igual con la tabla ACTIVAS sobre el campo alarmnum en descending.

Algo como (tendrás que revisar la sintaxis) :


CREATE INDEX IDX_CENTRAL_ENTRADADATOS ON CENTRAL (ENTRADADATOS DESCENDING);
  • 0

#11 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 31 diciembre 2009 - 11:07

luk2009 amigo que versión de Firebird usas??

Creo que es lo primero que debemos de saber para poder decirte a ciencia cierta que debes de hacer....
  • 0

#12 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 01 enero 2010 - 07:48

Marc y Rolphy gracias por sus respuestas.  Marc ya esos campos tienen un indice, ambos son primary keys,  pero son ascending, marc cual es la diferencia con eso.

Rolphy la base de datos es firebird 2.1

saludos

  • 0

#13 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 02 enero 2010 - 08:38

Hola Luk.

Los índices en Firebird son direccionales, de manera que se pueden recorrer en un sentido, pero no en el otro.

Para localizar un elemento determinado (where campo = X) no importa mucho el sentido del índice. Pero en este caso (first x from y order by z descending) queremos hacer un recorrido inverso del índice.

Recuerdo haber leído varias veces que los chicos de Firebird quieren hacer bidireccionales los índices. Pero por el problema que tienes, parece que está claro que en la última versión estable, que es la que tu utilizas (FB 2.1) aún no lo han implementado. Quizás en la FB 2.5 que ahora ya está en versión Release Candidate, ya funcionen los índices como bidireccionales, y tu programa no tendría ese problema.

Dado de que solo vas a perder unos pocos segundos para hacer la prueba, yo te recomiendo de que crees un par de índices DESCENDING para esas tablas, y vuelvas a probar tu programa. Ya nos dirás si eso ha ayudado (si no ha mejorado el rendimiento del programa, solo tienes que eliminar los índices, y ya lo vuelves a tener todo como antes).

Saludos.
  • 0

#14 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 02 enero 2010 - 11:39

Saludos.

luk2009 por lo que veo estas usando los componentes Zeos, no los he utilizado pero me imagino que tendrán dentro de su repertorio a un descendiente del DataSet.

En caso de ser positivo te recomiendo estudiar este componente que te permite tener todas las funciones en un solo componente: Insert, Update, Delete, , Select y Refresh*.

El Refresh de estos componentes van directamente amarrados a la sentencias que pongas, ejemplo:


sql
  1. SELECT CAMPO1, CAMPO2 FROM TABLA WHERE CAMPO1 = :OLD_CAMPO1



Con este componente te evitas el tener que hacer ese método que usas para insertar y de paso el evento AfterInsert que posiblemente el DataSet tenga una propiedad para refrescar después de una inserción y en caso de no tener dicha propiedad pues nada mas pones DataSet.Refresh y tu sentencia será light.

Ahora bien si no existe tal componente puedes utilizar la combinación Query + UpdateSQL y de este modo tendrás el DataSet solo que con dos.

Haz la prueba y nos avisa...
  • 0

#15 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 02 enero 2010 - 12:16

Hola,
Yo creo que es cosa de los índices como menciona Marc.
Para casos en los que se necesita de un uso "bidireccional" al recorrer una tabla (si es realmente tu caso) lo mejor es disponer de dos índices: uno ascendente y otro descendente.
Pero si sólo te limitas a consultas descendentes es de esperar que el índice sea descendiente y no ascendente como lo declaraste.

Como consejo, aunque no se si Zeos lo contempla, recurre al poder de los eventos de Firebird. Puedes disponer de un trigger After Insert para disparar el evento y luego capturarlo en tu sistema. Una vez que se captura dicho evento se cierra y abre nuevamente la consulta. Al menos entre los componentes IBX existe el componente IBEvents que justamente permite eso: "cachar" los eventos.

No estaría demás que revisases las transacciones. ¿Hay otras transacciones activas? ¿Demasiada concurrencia?

La lentitud puede ser explicada y deberse a varios factores. Si con los índices sigue siendo lento habrá que mirar por otro lado.

Saludos,
  • 0

#16 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 02 enero 2010 - 12:32

Saludos.

Delphius, no creo que el problema sea por indices si te fijas en el primer mensaje, notaras que el Query1 ya estaba abierto, luego lo cierra y limpia su sentencias para realizar un Open con 10 registros. Entonces fuerza un refresh y si no me equivoco en este caso ese Refresh estaría haciendo un FetchAll a la BD.

En cuanto a la transacción, entiendo que debes de revisar si haces commit después de la inserción, con esto también te ahorrarías el Refresh.
  • 0

#17 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 02 enero 2010 - 12:45

Pues no se amigo Rolphy,
Está confuso todo esto... o al menos yo lo estoy sintiendo así.

Ahora que releo me digo ¿Y porqué no disponer de un trigger after insert que haga el trabajo? Según parece, se desea insertar cierto registro en una tabla cuando se lleva a cabo una inserción en otra... Si es así, yo opino que lo mejor es emplear triggers.

Y ahora que lo mencionamos, no veo Commit de alguna transacción por ningún lado. No se como se manejan los componentes ZEOS pero tengo entendido que deben confirmarse la transacción.

Algo entra en juego los índices, no debería descartarse esa opción.

Saludos,
  • 0

#18 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 02 enero 2010 - 01:57

Saludos.

Delphius, de hecho con cualquier componente que hable con Firebird necesita hacer un Commit, por cada inserción, modificación o borrado que se efectúe en la Base de Datos sin haber abierto la transacción explícitamente.

El BDE se encarga de hacer el Commit cuando usas sus componentes, salvo cuando abres la transacción explícitamente que se debe llamar el Commit.
  • 0

#19 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 02 enero 2010 - 07:53

Bueno he creado los indices que me dice Marc y ha funcionado todo rapidisimo.

Rolphy sobre el commit ya enecumene me lo habia indicado y lo puse en el afterinsert de los dos querys en el datamodule:


delphi
  1. zconnection1.commit



Tenia la duda si debia ponerlo ahi o despues de hacer el insert con:


delphi
  1. DMmonitoreo.ZQuery2.CommitUpdates



Gracias Marc por el asunto de los indices, nunca se me habria ocurrido.

Gracias a todos por su ayuda, estoy probando, pero hasta ahora todo bien (y)
  • 0

#20 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 03 enero 2010 - 05:29

Saludos.

Posiblemente la segunda opción que presentas es cuando utilizas CacheUpdates y ese sea el método para aplicarlo a la Base de Datos.

Te reitero que estudies los DataSet, con ellos la vida se te hace más fácil.
  • 0




IP.Board spam blocked by CleanTalk.