Ver Mensaje Individual
  #1  
Antiguo 29-01-2008
Avatar de Ivanzinho
[Ivanzinho] Ivanzinho is offline
Miembro Premium
 
Registrado: ene 2005
Ubicación: Galicia
Posts: 595
Reputación: 20
Ivanzinho Va por buen camino
Funcionamiento de IBX y FIBPlus

Hola compañeros, les planteo una duda en base al funcionamiento de los componentes de acceso a datos IBX.

Estuve realizando pruebas de velocidad y concurrencia con componentes IBX y FIBPlus con una base de datos Firebird 2.0. Para esto realicé inserciones masivas en una tabla de la base de datos desde una aplicación realizada en Delphi 5 con el fin de determinar cuál de los componentes era más rápido y comprobar que en caso de producirse alguna colisión (violación de clave primaria), el programa lo detectase y continuase su ejecución. Cabe destacar también que las claves de los registros insertados deben ser consecutivas y que no puede haber saltos por el medio.

Las prueba se realizaron ejecutando la aplicación concurrentemente desde tres equipos distintos, que apuntaban a la misma B.D., durante 30 seg. y en diez ocasiones distintas para luego calcular la media de inserciones y colisiones. El código de los distintos procedimientos que utilizan en la inserción son los siguientes :

Rutina inserción y control de errores :
Código Delphi [-]
seguir := trae;
//mientras no termine la transacción correctamente o no se pueda resolver la excepción
while seguir do
  try
    dmDatos.StartTransaction;
    dmDatos.IBDSMovimientos.Insert;
    dmDatos.IBDSMovimientos.Post;
    dmDatos.Commit;
    seguir := false;
    AbrirTablas(false, 0,0); 
  except 
    dmDatos.Rollback;
    //Control de errores  
  end;

En el data module nos encontramos con los siguientes procedimientos :
Código Delphi [-]
//Inserción del registro, carga de datos por defecto
procedure TDMDatos.IBDSMovimientosAfterInsert(DataSet: TDataSet);
begin
  IBDsMovimientosNum_mr.Value := -1;
  IBDsMovimientosAno_mr.Value := Ano;
  IBDsMovimientosFgr_mr.Value := date;
  IBDsMovimientosRev_mr.Value := 0;
end;

procedure TDMDatos.StartTransaction;
begin
  if not IBTrFac.InTransaction then
    IBTrFac.StartTransaction; 
end;

procedure TDMDatos.Commit;
begin
  if IBTrFac.InTransaction then
    IBTrFac.Commit;
end;

procedure TDMDatos.Rollback;
begin
  if IBTrFac.InTransaction then
    IBTrFac.Rollback;
end;
NOTA : Con los componentes FIBPlus no hace falta comprobar la si la conexión está activa, lo hacen los componentes automáticamente, lo que no se es si se continúa con la transacción activa o se aborta y crea una nueva.

En la base de datos tenemos el siguiente trigger que es donde se calcula la clave primaria.
Código SQL [-]
CREATE trigger mbmovimientosrect_bi_actclave for mbmovimientosrect
active before insert position 0
AS
  declare variable v_clave integer;
begin
  Select max(Num_mr)
  from mbmovimientosrect
  where ano_mr = new.ano_mr
  into :v_clave;

  if (v_clave is null) then
    v_clave = 1;
  else
    v_clave = v_clave + 1;

   new.num_mr = v_clave;
end

Tras cada inserción masiva realizo un borrado de los registros de la base de datos, desde el IBExpert con una simple consulta delete from tabla para iniciar otra nueva inserción masiva. Con FIBPlus todo funciona correctamente, los registros se empiezan a insertar desde el 1, en cambio con IBX los registros se comienzan a insertar desde el último registro almacenado en el DataSet de la aplicación. Para que esto no suceda tuve que realizar un rollback antes de comenzar la transacción en el procedimiento de inserción. Este comportamiento me resulta sumamente extraño, ya que el calculo de la clave se realiza en un trigger fuera de la aplicación.

También probé a realizar la inserción desde otra transacción, pero el resultado era el mismo :
Código Delphi [-]
 Seguir := trae;
T := TIBTransaction.Create(nil);
  try
    T.DefaultDatabase := DMDatos.IBDBfac;

    Q := TIBSQL.Create(nil);
    try
      Q.Database := DMDatos.IBDBfac;
      Q.Transaction := DMDatos.IBTrFac;
      Q.SQL.Add('Insert into mbMovimientosRect(Num_mr, Ano_mr, Fgr_mr, Rev_mr)');
      Q.SQL.Add('Values(-1, :Ano, :Fecha, 0)');

      Q.Params.ByName('Ano').AsInteger := Ano;
      Q.Params.ByName('Fecha').AsDate := Now;

      while seguir do
        try
          T.StartTransaction;
          Q.ExecQuery;
          T.Commit;
          Seguir := false;
          DMDatos.Rollback;
          AbrirTablas
        except 
          //Control de errores
        end;
    finally
      Q.Free;
    end;
  finally
    T.Free;
  end;

Si has llegado hasta aquí te lo agradezco, pues he soltado un buen rollo . Mi pregunta es si alguien me puede decir a que se debe este comportamiento, ya que puede haber características importantes de IBX que desconozca.

Como nota de interés hay que decir que los resultados fueron mejores con FIBPlus, mayor velocidad en las inserciones y menor número de colisiones, pero los resultados obtenidos con IBX tampoco eran malos, por lo que en principio no compensa el desembolso económico que hay que realizar para adquirir los componentes FIB (a no ser que alguno de vosotros me de una razón para pensar lo contrario).

Un saúdo y muchas gracias por vuestra atención
__________________
Si no lees esto no vivirás tranquilo
Non lle poñades chatas â obra namentras non se remata. O que pense que vai mal que traballe n’ela; hai sitio para todos. (Castelao)
Responder Con Cita