PDA

Ver la Versión Completa : MySQL LENTO al hacer INSERT INTO sucesivamente


golf2008
18-11-2008, 21:49:43
Hola a todos:
Les cuento a ver si a alguien le pasó. Trabajo con Delphi 5 y Zeos.
Con MySQL todo bien, pero a la hora de tener que hacer varios INSERT INTO (dentro de un ciclo), se pone demasiado lento.

Para los que han realizado un sistema comercial integrado con la contabilidad de la empresa, cada vez que se registra una factura hay que hacer un asiento contable por cada producto que integra la factura, dado que cada producto puede tener una imputación contable distinta.

Supongamos una factura de 20 productos, me demora 9 segundos viendo el TXT del ZSQLMonitor. Ni quiero pensar implementado en red lo que va a demorar.

Desde ya muchas gracias.

AzidRain
19-11-2008, 00:05:29
Nada tiene que ver la lentitud en tu caso con el motor. No das muestra de código, lo cual ayudaría mucho. Yo hice algo similar y como lo ataqué fue creando una clase TAsientoFactura a la que le paso el ID de la factura que quiero contabilizar y hago ahi toda la lógica.

Si pones el trozo de código que contiene el ciclo te podremos ayudar un poco màs.

golf2008
19-11-2008, 13:06:21
Va el código:
Por cada producto este código se ejecuta tres veces, una por cada renglón del asiento. Si la factura tiene 20 producto, el código se ejecuta unas 60 veces

MD.ZAsientos.SQL.Clear;
MD.ZAsientos.SQL.Text:='INSERT INTO asientos (fecha,cuenta,debe,haber,saldo,comentario,numero,comp,numcom,codprov)'+
'VALUES (:fecha,:cuenta,:debe,:haber,:saldo,:comentario,:numero,:comp,:numcom,:codprov)';
MD.ZAsientos.ParamByName('fecha').Value:=StrtoDate(fecha.text);
MD.ZAsientos.ParamByName('cuenta').Value:=MD.DetalleImputa.Value;
MD.ZAsientos.ParamByName('Debe').Value:=MD.DetalleNetograv.Value;
MD.ZAsientos.ParamByName('comentario').Value:=comentario;
MD.ZAsientos.ParamByName('Numero').value:=nasiento;
MD.zAsientos.ParamByName('Comp').value:=MD.DetalleTipo.Value;
MD.zAsientos.ParamByName('Numcom').Value:=MD.DetalleNumcom.Value;
MD.zAsientos.ParamByName('Codprov').Value:=MD.DetalleCod_prov.Value;
MD.ZAsientos.ExecSQL;

Desde ya muchas gracias

seoane
19-11-2008, 13:22:19
Hace poco tuve que hacer un programa que básicamente hacia un montón de Insert en una tabla de MySql y el proceso tardaba muchísimo (te podías ir a tomar un café :D ), hasta que descubrí que MySql permite la inserción múltiple, es decir, insertar varios registros de una vez.

Por ejemplo (ayuda de MySQL (http://dev.mysql.com/doc/refman/5.0/en/insert.html)):

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);


Podrías probar a construir tu mismo la consulta e insertar todos los productos de la factura en una sola sentencia.

duilioisola
19-11-2008, 14:16:57
Y no tendrá que ver con las transacciones?
Yo trabajo con Firebird y depende de si utilizo Commit o CommitRetaining, la cosa cambia mucho.
while (no_se_terminen_los_datos) do
begin
if (not MD.ZAsientos.Transaction.InTransaction) then
MD.ZAsientos.Transaction.StartTransaction;
MD.ZAsientos.SQL.Clear;
MD.ZAsientos.SQL.Text:='INSERT INTO asientos (fecha,cuenta,debe,haber,saldo,comentario,numero,comp,numcom,codprov) '+
'VALUES (:fecha,:cuenta,:debe,:haber,:saldo,:comentario,:numero,:comp,:numcom,:codprov)';
MD.ZAsientos.ParamByName('fecha').Value:=StrtoDate(fecha.text);
MD.ZAsientos.ParamByName('cuenta').Value:=MD.DetalleImputa.Value;
MD.ZAsientos.ParamByName('Debe').Value:=MD.DetalleNetograv.Value;
MD.ZAsientos.ParamByName('comentario').Value:=comentario;
MD.ZAsientos.ParamByName('Numero').value:=nasiento;
MD.zAsientos.ParamByName('Comp').value:=MD.DetalleTipo.Value;
MD.zAsientos.ParamByName('Numcom').Value:=MD.DetalleNumcom.Value;
MD.zAsientos.ParamByName('Codprov').Value:=MD.DetalleCod_prov.Value;
MD.ZAsientos.ExecSQL;
MD.ZAsientos.Transaction.Commit;
end;

También puede tener que ver con los triggers que ejecute al insertar en esa tabla.

heymatias
19-12-2008, 00:59:54
Hola, soy nuevo en el foro y nuevo con Delphi. Pero laburo con MySQL desde hace años y te aseguro que hacer varias insersiones es muchísimo más lento que hacer una inserción enorme que haga todo.

Podés hacer una consulta del tipo

INSERT INTO.... ; INSERT INTO...;INSERT INTO.... ; INSERT INTO...;

... y así. La idea es que mover el motor de MySQL cuesta un poco, y si vos hacés todas las inserciones por separado lo estás moviendo cada vez, en cambio, si le dás todas las inserciones para hacer él se encarga de optimizar las mismas.

Cuanto más puedas delegar al motor mejor, está muy bien programado y nada de lo que vos programes va a ser más rápido.


Y fijate de hacer transacciones, porque si grabás la factura y no los asientos vas a tener problemas.


Saludos, matías.-